Eliminar filas que contienen NA en cada columna

8

Tengo un archivo delimitado por tabulaciones que se ve así:

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

El número de campos en cada línea es fijo e igual. Quiero eliminar esas filas del archivo anterior donde todos los campos para cada fila desde la columna 2 hasta la última es NA. Entonces la salida debería verse así:

gene    v1  v2  v3  v4
g2  NA  NA  2   3
g4  1   2   3   2 
usuario3138373
fuente
Si los campos que no son NA siempre son enteros no negativos, una expresión regular tan simple como \s\ddiferencia entre las líneas "buenas" y "malas".
Roman Odaisky
si está haciendo un trabajo de bioinformática, ¿por qué no usar R
qwr el
Debido a que estoy usando herramientas de línea de comando en sentido ascendente para generar este archivo y preferiré una solución awk o perl si no tengo que guardar el archivo para abrirlo en R. Por supuesto, en R puedes eliminar esto con un is.na cheque si lo creo
user3138373

Respuestas:

16

Con awk:

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

Recorra los campos que comienzan en el segundo campo e imprima la línea si se encuentra un campo que no contiene NA. Luego rompe el bucle.

Freddy
fuente
10

Usando GNU sed

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

Breve explicación:

g[0-9]\+\(\s*NA\s*\)\+$es una coincidencia de expresiones regulares gseguida de al menos un dígito, luego cualquier número de NAs con espacios opcionales entre hasta el final de la línea.

sed -e '/<regex>/d' elimina todas las líneas que coinciden <regex>

Una expresión regular más estándar con el mismo significado sería:

sed -Ee '/g[0-9]+([[:space:]]*NA[[:space:]]*)+$/d' filename
eike
fuente
44
Tenga en cuenta que \+y \sson expresiones regulares no estándar y coincidirán con una simple +o sen la mayoría de las sedversiones. Use en \{1,\}lugar de \+y en [[:space:]]lugar de \stener un código portátil.
Philippos
9

Con alldel módulo Perl List :: 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
conductor de acero
fuente
9

Con grep:

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

Esto hace que grep no muestre las -vlíneas ( ) donde la línea completa ( -x) coincide:

  • minúscula g en la primera columna, seguida de uno o más dígitos
  • cualquier número de instancias de espacios en blanco seguidos de NA
  • espacio en blanco final opcional
Jim L.
fuente
1
1, pero tenga en cuenta también que el número de campos es fija, por lo que podría utilizar {4}en lugar de *después de que el NAgrupo, y es posible que desee cambiar el primer [[:blank:]]*a [[:blank:]]+hacer los separadores de espacio en blanco obligatoria. De todos modos, nunca he entendido por qué todos insisten en sacar la awkbazuca para resolver estos simples problemas de filtrado que se grepmanejan fácilmente.
Kevin
Gracias por los comentarios, @Kevin. Incorporé su primera sugerencia, pero estoy reteniendo la otra *para que esta solución funcione igualmente bien para cualquier número arbitrario de NAcolumnas, siempre que sean todas NA.
Jim L.
2

Tu podrías intentar:

$ 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 
Rakesh Sharma
fuente