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.