2013-11-01 31 views
2

我在R中問了這個問題,並得到了很多答案,但是所有這些答案在運行了幾個小時後都會讓我的4Gb Ram計算機崩潰,或者他們需要很長時間才能完成。 faster way to compare rows in a data frame快速比較數據集中的行的方法

有人說這不是在R做的工作。因爲我不知道C和我在Perl上有點流利,所以我會在這裏問。

我想知道是否有一種快速的方法來比較大型數據集的每一行與其他行,以確定具有特定同源性程度的行。比方說,下面是簡單的例子,我想同源性> = 3

data: 
sample_1,10,11,10,13 
sample_2,10,11,10,14 
sample_3,10,10,8,12 
sample_4,10,11,10,13 
sample_5,13,13,10,13 

輸出應該是這樣的:

output 
    sample duplicate matches 
1 sample_1 sample_2  3 
2 sample_1 sample_4  4 
3 sample_2 sample_4  3 
+0

也許嘗試['領帶::陣列:: CSV'](HTTP:// search.cpan.org/perldoc?Tie%3A%3AArray%3A%3ACSV) – TLP

+0

它花了我30多分鐘來寫一個腳本,所以不打擾:) – Vorsprung

+0

命令重要嗎?例如10,11,10,13和11,11,10,13應該返回3個匹配還是0個匹配? – psxls

回答

1

該解決方案提供了一個替代直接比較,這將是緩慢的大數據量。 基本思想是在讀取數據時建立倒排索引。 如果每列有許多不同的值,這會使比較更快。 對於每一行,您查找索引並計算匹配 - 這樣您只能考慮實際發生此值的示例。 您可能仍然有內存問題,因爲索引與數據一樣大。 爲了克服這一點,您可以縮短樣本名稱並使用持久索引(例如,使用DB_File)。

use strict; 
use warnings; 
use 5.010; 

my @h; 

my $LIMIT_HOMOLOGY = 3; 

while(my $line = <>) { 
    my @arr = split /,/, $line; 

    my $sample_no = shift @arr; 
    my %sim; 
    foreach my $i (0..$#arr) { 
     my $value = $arr[$i]; 
     our $l; 
     *l = \$h[$i]->{$value}; 
     foreach my $s (@$l) { 
      $sim{$s}++; 
     } 
     push @$l, $sample_no; 
    } 
    foreach my $s (keys %sim) { 
     if ($sim{$s}>=$LIMIT_HOMOLOGY) { 
      say "$sample_no: $s. Matches: $sim{$s}"; 
     } 
    } 
} 

對於25000行,26列,隨機整數值介於1和100之間,程序花了69秒在我的Mac書籍空間完成。

1

匹配計算當兩個線對相同的位置相同的數字,

perl -F',' -lane' 
    $k = shift @F; 
    for my $kk (@o) { 
    $m = grep { $h{$kk}[$_] == $F[$_] } 0 .. $#F; 
    $m >=3 or next; 
    print ++$i, " $kk $k $m"; 
    } 
    push @o, $k; 
    $h{$k} = [ @F ]; 
' file 

輸出,

1 sample_1 sample_2 3 
2 sample_1 sample_4 4 
3 sample_2 sample_4 3 
+0

簡直棒極了!在'map'格式中使用'grep'使我驚訝!從您的解決方案學習。 – jkshah

+0

@jkshah我很高興你覺得它很有用:) –

+0

你可以請你的代碼與更大的輸入尺寸基準嗎?他有26列和250,000行輸入數據。我已經在[我的Rcpp解決方案](http://stackoverflow.com/a/19730940/1412059)中對25,000行進行了基準測試,並且希望看到perl中的性能。 – Roland