Menghapus baris yang mengandung NA di setiap kolom

8

Saya memiliki file yang dibatasi tab yang terlihat seperti ini:

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

Jumlah bidang di setiap baris adalah tetap dan sama. Saya ingin menghapus baris-baris itu dari file di atas di mana semua bidang untuk setiap baris dari kolom 2 hingga terakhir adalah NA. Maka output akan terlihat seperti:

gene    v1  v2  v3  v4
g2  NA  NA  2   3
g4  1   2   3   2 
pengguna3138373
sumber
Jika bidang non-NA selalu bilangan bulat tidak negatif, ekspresi reguler sesederhana \s\dmembedakan antara garis "baik" dan "buruk".
Roman Odaisky
Jika Anda melakukan pekerjaan bioinformatika, mengapa tidak menggunakan R
qwr
Karena saya menggunakan alat baris perintah hulu untuk menghasilkan file ini dan saya akan lebih suka awk atau perl solusi jika saya tidak harus menyimpan file untuk dibuka di R. Tentu saja di R Anda dapat menghapus ini dengan is.na memeriksa jika saya pikir
user3138373

Jawaban:

16

Dengan awk:

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

Ulangi bidang yang dimulai dari bidang kedua dan cetak baris jika bidang yang tidak berisi NAditemukan. Kemudian pecahkan loop.

Freddy
sumber
10

Menggunakan GNU sed

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

Penjelasan singkat:

g[0-9]\+\(\s*NA\s*\)\+$adalah pencocokan regex gdiikuti oleh setidaknya satu digit, kemudian sejumlah NAs dengan spasi opsional antara hingga akhir baris.

sed -e '/<regex>/d' menghapus semua baris yang cocok <regex>

Regexp yang lebih standar dengan arti yang sama adalah:

sed -Ee '/g[0-9]+([[:space:]]*NA[[:space:]]*)+$/d' filename
Eike
sumber
4
Harap dicatat bahwa \+dan \smerupakan ekspresi reguler non-standar dan akan cocok dengan yang sederhana +atau sdalam kebanyakan sedversi. Gunakan \{1,\}alih-alih \+dan [[:space:]]alih-alih \smemiliki kode portabel.
Philippos
9

Dengan alldari Perl List :: Util module:

$ 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
Steeldriver
sumber
9

Dengan grep:

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

Ini menyebabkan grep tidak menampilkan ( -v) baris di mana seluruh baris ( -x) cocok:

  • huruf kecil g di kolom pertama, diikuti oleh satu atau lebih digit
  • sejumlah contoh spasi putih diikuti oleh NA
  • spasi tambahan trailing opsional
Jim L.
sumber
1
1, tapi perhatikan juga bahwa jumlah bidang adalah tetap, sehingga Anda bisa menggunakan {4}bukannya *setelah NAkelompok, dan Anda mungkin ingin mengubah yang pertama [[:blank:]]*untuk [[:blank:]]+membuat pemisah spasi wajib. Bagaimanapun, saya tidak pernah mengerti mengapa semua orang bersikeras mengeluarkan awkbazooka untuk memecahkan masalah penyaringan sederhana yang grepmudah ditangani.
Kevin
Terima kasih atas umpan baliknya, @Kevin. Saya memasukkan saran pertama Anda, tetapi saya mempertahankan yang lain *sehingga solusi ini bekerja dengan baik untuk jumlah NAkolom yang berubah-ubah , asalkan semuanya NA.
Jim L.
2

Kamu bisa mencoba:

$ 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
sumber