【问题标题】:fast way to compare rows in a dataset比较数据集中行的快速方法
【发布时间】:2025-12-04 18:50:02
【问题描述】:

我在 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

【问题讨论】:

  • 或许可以试试Tie::Array::CSV
  • 我花了 30 多分钟来写一个脚本,所以不打扰:)
  • 订单重要吗?例如 10,11,10,13 和 11,11,10,13 应该返回 3 个匹配还是 0 个匹配?
  • 应该返回 3 个匹配项。
  • 10,11,12,138,9,10,11 有多少匹配项?

标签: perl


【解决方案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

【讨论】:

  • 简直太棒了!在map 格式中使用grep 让我感到惊讶!从您的解决方案中学习。
  • @jkshah 我很高兴你觉得它有用:)
  • 您能否用更大的输入大小对您的代码进行基准测试?他有 26 列和 250,000 行的输入数据。我在 my Rcpp solution 中对多达 25,000 行进行了基准测试,并且有兴趣查看 perl 中的性能。
  • @Roland 我会但没有您的输入文件,而且我不熟悉 R/Rcpp。对于一些快速的结果,你可以检查date; perl ...; date
  • @mpapec 我不熟悉 perl。
【解决方案2】:

此解决方案提供了直接比较的替代方法,直接比较对于大量数据会很慢。 基本思想是在读取数据的同时建立倒排索引。 如果每列有很多不同的值,这会使比较更快。 对于每一行,您查找索引并计算匹配项 - 这样您只考虑实际出现该值的样本。 您可能仍然存在内存问题,因为索引与您的数据一样大。 为了克服这个问题,您可以缩短示例名称并使用持久索引(例如,使用 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 秒才能完成。

【讨论】: