是否可以使用 Perl 合并具有不同行数的数据框?

Is it possible to merge data frames with different amounts of rows using Perl?

我有一个我无法解决的小问题。

我有两个数据框 (DF):第一个 (Main DF) 有 8 列和 45918 行,第二个 (Complementary DF) 有 4 列和 97969 行。 如果你想看完整的DF,这里是我的GitHub的link:https://github.com/MauriAndresMU1313/Example_Merge_Dataframes

这里有一个例子,看起来像 DF。

主要方向:

ID1          ID2         dN          dS          Omega       Label_ID1       Label_ID2       Group
AVP78042     AVP78031    0.0059      0.1188      0.0500      SARSr-bat-CoV   SARSr-bat-CoV   Intra
ATO98108     AVP78031    0.1373      1.4673      0.0936      SARSr-bat-CoV   SARSr-bat-CoV   Intra
ATO98108     AVP78042    0.1371      1.4224      0.0964      SARSr-bat-CoV   SARSr-bat-CoV   Intra

互补DF:

Distance    ID_1        ID_2        Value
DISTANCE    AVP78042.1  ATO98108.1  0.29731
DISTANCE    AVP78042.1  ATO98120.1  0.29281
DISTANCE    AVP78042.1  ATO98132.1  0.33095

在这种情况下,我的主要目标是合并互补的列(ID_1、ID_2Value) 到主 DF。两种情况下的 ID_1 和 ID_2 是相同的,但是顺序不同。

为此,我想在两个数据帧之间进行 ID_1 和 2 之间的匹配,当匹配为真时将列值(补充 DF)添加到主 DF。 我认为在“如果”条件下这样做。 这里的问题可能是每个 DF 之间的行数和标签顺序(ID_1 和 ID_2)不同。
以前,我使用 Perl 脚本合并 DF:


use strict;
use warnings;
use feature qw{ say };

sub load {
    my ($file, $table, $phase) = @_;
    open my $in, '<', $file or die "$file: $!";
    while (<$in>) {
        chomp;
        my @columns = split /\t/;
        my $id = join '_', @columns[0, 1];
        die "Duplicate $id."
            if 'first' eq $phase && exists $table->{$id};

        push @{ $table->{$id} }, $columns[2];
        say join "\t", @columns[0, 1], @{ $table->{$id} }
            if 'print' eq $phase;
    }
}

my %table;
my $phase = 'first';
while (my $file = shift @ARGV) {
    load($file, \%table, $phase);
    $phase = 1 == @ARGV ? 'print' : '';
}

我认为要完成此脚本以实现我的新目标,我需要一个“if”条件来生成 ID 之间的匹配项。 这是一个可能的输出示例:

ID1          ID2         dN          dS          Omega   Value   Label_ID1       Label_ID2       Group
AVP78042     AVP78031    0.0059      0.1188      0.0500 0.29731  SARSr-bat-CoV   SARSr-bat-CoV   Intra
ATO98108     AVP78031    0.1373      1.4673      0.0936    -     SARSr-bat-CoV   SARSr-bat-CoV   Intra

我将“-”放在值列中以显示 ID_1 和 ID_2 之间“不匹配”的示例。

我尝试了不同的方法,但是,我仍然无法解决问题。

对此有何建议或意见?

更改我的输入文件后:

Main DF:
ID1          ID2         dN          dS          Omega
AVP78042     AVP78031    0.0059      0.1188      0.0500 
ATO98108     AVP78031    0.1373      1.4673      0.0936 
ATO98108     AVP78042    0.1371      1.4224      0.0964 
...
Complementary DF:
ID1          ID2        Value
AVP78042.1  ATO98108.1  0.29731
AVP78042.1  ATO98120.1  0.29281
...

此脚本在 ID 之间匹配时合并列:

#!/usr/bin/perl
use strict;
use warnings;

my $file01 = $ARGV[0];
my $file02 = $ARGV[1];
my @content02;

open (B, $file02) or die;
while (my $l1 = <B>) {
  $l1 =~ s/\n//g;
  $l1 =~ s/\r//g;
  $l1 =~ s/^ //g;
  push @content02, $l1 ;
}
close B;

### Running with the first file ()
open (A, $file01) or die;

LINE:
while (my $l2 = <A>) { # From file 1 (ref)
  $l2 =~ s/\n//g;
  $l2 =~ s/\r//g;
  $l2 =~ s/ //g;
  my @matrix_2 = split ("\t", $l2);
  my $two_id_01 = $matrix_2[0]; ### No tiene punto
  my $two_id_02 = $matrix_2[1]; ### No tiene punto

  foreach my $q (@content02) { ### From file 2
    my @matrix_q = split ("\t", $q);
    my $q_id_01 = $matrix_q[0];
    my $q_id_02 = $matrix_q[1];
    my $value = $matrix_q[2];

    if (($q_id_01 =~ /^$two_id_01/) and ( $q_id_02 =~ /^$two_id_02/) ) {
      print "$l2\t$value\n";
      next LINE;
    }
  }
}


close A;

exit;

输出:

Merge DF (6 columns x 42336 rows) 
ID1          ID2         dN     dS      Omega   Value
ATO98108    AVP78042    0.1371  1.4224  0.0964  0.29731
ATO98120    AVP78042    0.1376  1.2989  0.1060  0.29281