2013-11-01 32 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