Xóa các hàng chứa NA trong mỗi cột


8

Tôi có một tệp được phân định bằng tab trông như thế này:

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

Số lượng các trường trong mỗi dòng là cố định và giống nhau. Tôi muốn xóa các hàng đó khỏi tệp trên, trong đó tất cả các trường cho mỗi hàng từ cột 2 đến cuối cùng là NA. Sau đó, đầu ra sẽ như:

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

Nếu các trường không phải NA luôn là các số nguyên không âm, thì một biểu thức chính quy đơn giản như \s\dphân biệt giữa các dòng tốt và các dòng xấu Bad.
Roman Odaisky

nếu bạn đang làm công việc tin sinh học tại sao không sử dụng R
qwr

Bởi vì tôi đang sử dụng các công cụ dòng lệnh ngược dòng để tạo tệp này và tôi sẽ thích giải pháp awk hoặc perl hơn nếu tôi không phải lưu tệp để mở trong R. Tất nhiên trong R bạn có thể xóa tệp này bằng cách is.na kiểm tra nếu tôi nghĩ
user3138373

Câu trả lời:


16

Với awk:

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

Lặp lại các trường bắt đầu từ trường thứ hai và in dòng nếu NAtìm thấy trường không chứa . Sau đó phá vỡ vòng lặp.


10

Sử dụng GNU sed

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

Giải thích ngắn gọn:

g[0-9]\+\(\s*NA\s*\)\+$là một kết hợp regex gtheo sau bởi ít nhất một chữ số, sau đó bất kỳ số NAs nào có khoảng trắng tùy chọn giữa cho đến cuối dòng.

sed -e '/<regex>/d' xóa tất cả các dòng khớp <regex>

Một biểu thức chính quy chuẩn hơn với cùng ý nghĩa sẽ là:

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

4
Xin lưu ý rằng \+\slà các biểu thức chính quy không chuẩn và sẽ khớp với một đơn giản +hoặc strong hầu hết sedcác phiên bản. Sử dụng \{1,\}thay vì \+[[:space:]]thay vì \sđể có mã di động.
Phi

9

Với alltừ danh sách Perl :: mô-đun 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

Với grep:

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

Điều này khiến grep không hiển thị -vcác dòng ( ) trong đó toàn bộ dòng ( -x) khớp:

  • chữ thường g trong cột đầu tiên, theo sau là một hoặc nhiều chữ số
  • bất kỳ số lượng các khoảng trắng theo sau bởi NA
  • khoảng trắng theo dõi tùy chọn

1
+1, nhưng cũng lưu ý rằng số lượng trường được cố định, vì vậy bạn có thể sử dụng {4}thay vì *sau NAnhóm và bạn có thể muốn thay đổi trường đầu tiên [[:blank:]]*để [[:blank:]]+bắt buộc các dấu tách khoảng trắng. Bất kể, tôi chưa bao giờ hiểu lý do tại sao mọi người khăng khăng rút awkbazooka để giải quyết các vấn đề lọc đơn giản này grepxử lý dễ dàng.
Kevin

Cảm ơn bạn đã phản hồi, @Kevin. Tôi đã kết hợp đề xuất đầu tiên của bạn, nhưng tôi vẫn giữ nguyên đề xuất khác *để giải pháp này hoạt động tốt như nhau cho bất kỳ số lượng NAcột tùy ý nào , miễn là tất cả chúng đều là NA.
Jim L.

2

Bạn có thể thử:

$ 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 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.