我有10列和200行的製表符分隔的文件:
從行中檢索數據的條件下
a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
e f 1 0 1 0 0 1 0 0
等,以提取數據的條件是,「如果從第3列到最後一列,0數超過4,它不應該採取該行考慮」
對於上面設置的答案是:
a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
請幫助,我嘗試和失敗。
shell,python或PERL中的任何東西都可以。
謝謝。
我有10列和200行的製表符分隔的文件:
從行中檢索數據的條件下
a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
e f 1 0 1 0 0 1 0 0
等,以提取數據的條件是,「如果從第3列到最後一列,0數超過4,它不應該採取該行考慮」
對於上面設置的答案是:
a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
請幫助,我嘗試和失敗。
shell,python或PERL中的任何東西都可以。
謝謝。
import csv
fin = open("text.txt","rb")
r = csv.reader(fin,delimiter="\t")
for line in r:
if (sum(1 if x=='0' else 0 for x in line[3:]) < 4):
print line
fin.close()
如果AWK是可以接受的,請嘗試:
awk '{
c = x
for (i = f - 1; ++i <= NF;)
$i == 0 && c++
}
c > l' l=4 f=3 infile
鑑於你的文件格式,這可能工作太:
awk '{ r = $0 }
gsub(/0/, x, r) > l
' l=4 infile
下面是一個例子 - Perl寫的。請注意,你說「不會考慮4個以上的零」,並且實際上只會在示例輸出中考慮超過4個零的行。
use strict;
use warnings;
while (<DATA>) {
chomp;
my ($id1, $id2, @remaining_columns) = split;
my @zeros = grep { $_ == 0 } @remaining_columns;
if (@zeros > 4) {
print "$_\n";
}
}
__DATA__
a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
e f 1 0 1 0 0 1 0 0
我的錯......錯樣輸出 – Angelo 2012-01-04 13:43:03
這裏的東西,忽略任何非數字.....
line = "a b 2 1 2 2 3 2 3 2"
if (sum(map(int,filter(str.isdigit,line.split(" "))))) < 4:
print line
oopps didn這個問題沒有正確地讀出來......認爲總數必須小於4 ...... – 2012-01-04 13:43:05
根據您當前例子(沒有在第一和第二列中沒有0)。
AWK:
awk '{x=$0;gsub(/[^0]/,"",x);}length(x)>4' yourFile
測試:
kent$ echo "a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
e f 1 0 1 0 0 1 0 0
"|awk '{x=$0;gsub(/[^0]/,"",x);}length(x)>4'
輸出:
e f 1 0 1 0 0 1 0 0
我也感到困惑,你想要的0> 4或< 4的行數???
在(略)慣用的Perl。
#!/usr/bin/perl
use strict;
use warnings;
while (<DATA>) {
my (undef, undef, @cols) = split;
print if (grep $_ == 0, @cols) > 4
}
__DATA__
a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
e f 1 0 1 0 0 1 0 0
像揚哈通說,你的問題的描述不符所需的輸出,但如果你想有超過4個零的行,這會做:
perl -ane 'print if grep(/^0$/,@F) > 4' data.tsv
我假定第一和第二欄不會包含1或0。如果不是這種情況,請改用grep(/^0$/, @F[2..9])
。
下面是使用List :: MoreUtils的一個不同的Perl解決方案。
use strict;
use warnings;
use List::MoreUtils qw/true/;
while (my $line = <DATA>) {
my ($ch1, $ch2, @arr) = split /\s+/, $line;
print $line if ((true {$_ == 0} @arr) > 4);
}
__DATA__
a b 1 0 1 1 0 1 0 0
c d 0 0 0 1 1 1 1 0
e f 1 0 1 0 0 1 0 0
請告訴我們你的嘗試 - 也許你的一些代碼也會很好! – codeling 2012-01-04 13:30:34
由於0的出現不是,僅限於某一列,並且它可以出現在任何列中,所以邏輯本身在那裏失敗。 :( – Angelo 2012-01-04 13:31:57
aw,來吧,基本的邏輯非常簡單:讀取行,從第三個開始總結令牌;如果總和大於4,則丟棄該行,否則使用它。有問題嗎? – codeling 2012-01-04 13:36:38