Rimozione di righe contenenti NA in ogni colonna


8

Ho un file delimitato da tabulazioni che assomiglia a questo:

gene    v1  v2  v3  v4
g1  NA  NA  NA  NA
g2  NA  NA  2   3
g3  NA  NA  NA  NA
g4  1   2   3   2

Il numero di campi in ogni riga è fisso e uguale. Voglio rimuovere quelle righe dal file sopra dove tutti i campi per ogni riga dalla colonna 2 all'ultima sono NA. Quindi l'output dovrebbe apparire come:

gene    v1  v2  v3  v4
g2  NA  NA  2   3
g4  1   2   3   2 

Se i campi non NA sono sempre numeri interi non negativi, un'espressione regolare semplice quanto \s\ddistingue tra le linee "buona" e "cattiva".
Roman Odaisky,

se stai facendo un lavoro bioinformatico, perché non usare R
qwr

Perché sto usando gli strumenti da riga di comando a monte per generare questo file e preferirò la soluzione awk o perl se non devo salvare il file per aprirlo in R. Ovviamente in R puoi rimuoverlo con is.na spunta se penso
user3138373

Risposte:


16

Con awk:

awk '{ for (i=2;i<=NF;i++) if ($i!="NA"){ print; break } }' file

Scorrere i campi a partire dal secondo campo e stampare la riga se NAviene trovato un campo non contenente . Quindi interrompere il ciclo.


10

Usando GNU sed

sed -e '/g[0-9]\+\(\s*NA\s*\)\+$/d' filename

Breve spiegazione:

g[0-9]\+\(\s*NA\s*\)\+$è una corrispondenza regex gseguita da almeno una cifra, quindi un numero qualsiasi di NAs con spazi opzionali tra fino alla fine della riga.

sed -e '/<regex>/d' elimina tutte le righe corrispondenti <regex>

Una regexp più standard con lo stesso significato sarebbe:

sed -Ee '/g[0-9]+([[:space:]]*NA[[:space:]]*)+$/d' filename

4
Si prega di notare che \+e \ssono le espressioni regolari non-standard e corrisponderà un semplice +o snella maggior parte delle sedversioni. Utilizzare \{1,\}invece di \+e [[:space:]]invece di \savere un codice portatile.
Philippos,

9

Con alldall'elenco Perl :: Modulo Util:

$ perl -MList::Util=all -alne 'shift @F; print unless all { $_ eq "NA" } @F' file
gene  v1  v2  v3  v4
g2    NA  NA  2   3
g4    1   2   3   2

9

Con grep:

egrep -v -x 'g[0-9]+([[:blank:]]+NA)*[[:blank:]]*' filename

Questo fa sì che grep non visualizzi le -vrighe ( ) in cui l'intera riga ( -x) corrisponde:

  • minuscola g nella prima colonna, seguita da una o più cifre
  • qualsiasi numero di istanze di spazi bianchi seguito da NA
  • spazi bianchi finali opzionali

1
+1, ma nota anche che il numero di campi è fissa, quindi è possibile utilizzare {4}al posto del *dopo il NAgruppo, e si consiglia di cambiare il primo [[:blank:]]*a [[:blank:]]+fare i separatori spazi bianchi obbligatoria. Indipendentemente da ciò, non ho mai capito perché tutti insistano nel tirare fuori il awkbazooka per risolvere questi semplici problemi di filtraggio che grepgestiscono facilmente.
Kevin,

Grazie per il feedback, @Kevin. Ho incorporato il tuo primo suggerimento, ma sto trattenendo l'altro in *modo che questa soluzione NAfunzioni ugualmente bene per qualsiasi numero arbitrario di colonne, purché siano tutte NA.
Jim L.

2

Puoi provare:

$ grep -P '\t(?!NA(\t|$))' file

$ sed -e 'h;s/\tNA//g;/\t/!d;g' file

$ perl -MList::MoreUtils=any -F'\t' -lane 'print if any { ! /^NA$/ } @F[1..$#F]' file 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.