2

我在 R 中问了这个问题并得到了很多答案,但是它们都在运行几个小时后使我的 4Gb Ram 计算机崩溃,或者它们需要很长时间才能完成。 比较数据框中的行的更快方法

有人说用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
4

2 回答 2

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
于 2013-11-02T09:43:16.380 回答
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}";
        }
    }
}

对于 26 列的 25000 行,随机整数值介于 1 到 100 之间,该程序在我的 mac book air 上花费了 69 秒才能完成。

于 2013-11-01T22:04:57.887 回答