【问题标题】:Building matrix with values from multiple files使用来自多个文件的值构建矩阵
【发布时间】:2021-06-19 19:33:43
【问题描述】:

我有多个文件需要创建一个具有匹配值的矩阵

File_1,它是主文件,包含所有数字制表符,以一行分隔

  Sample_1   23   45   46   67   78   47   98   73   87   45   97   21

有多个文件,如果数字匹配,则在上面的文件中添加 1 或添加 0

文件_2

Sample_2
23
67
47
235
87
102
97

文件_3

Sample_3
67
51
78
98
52
12
21
124

输出

Sample_1   23   45   46   67   78   47   98   73   87   45   97   21
Sample_2   1    0    0    1    0    1    0    0    1    0    1    0
Sample_3   0    0    0    1    1    0    1    0    0    0    0    1 

【问题讨论】:

  • 请在您的问题中以代码的形式添加您的努力,这是非常鼓励的,谢谢。
  • 输出文件中第 2 行以后的顺序重要吗?如果是,是什么决定的?
  • 文件第 2,3 行等的顺序并不重要,但列的顺序将是标准的,因为它们代表基因组中通常按递增顺序排列的位置

标签: python awk


【解决方案1】:

对于给定的输入,使用低于 1 的 gawk 会产生所需的 o/p。

输入:

$ cat f1
Sample_1   23   45   46   67   78   47   98   73   87   45   97   21

$ cat f2
Sample_2
23
67
47
235
87
102
97

Sample_3
67
51
78
98
52
12
21
124

脚本:

$ cat t.sh 
#!/usr/bin/env bash

awk -v OFS="\t" '
            NR==1{                             
                  $1=$1; total = split($0, arr); print; nextfile
            }
            function print_rec( i){
             if(has_old)
               for(i=2; i in arr; i++)
                  printf("%s%s",(arr[i] in farr ? 1 : 0 ) , (i<total ? OFS:RS) )
            }
            /^Sample_*/{
                   print_rec(); delete farr;
                   printf ("%s%s",$1, OFS); next 
            }
            NF{
                   farr[$1]; has_old=1;   
            }
            END{
                print_rec();
            }' f1 f2 

输出:

$ chmod +x t.sh 
$ ./t.sh 
Sample_1    23  45  46  67  78  47  98  73  87  45  97  21
Sample_2    1   0   0   1   0   1   0   0   1   0   1   0
Sample_3    0   0   0   1   1   0   1   0   0   0   0   1

【讨论】:

  • 谢谢。这对我以及上面的 awk 解决方案都很有效
  • @Empyreanrocks 如果你想提供多个文件,那么只需将 /^Sample_*/{ 替换为 FNR==1{
  • 感谢您的评论。我已经编辑了我的问题,因为我在发布后发现我的 File_2 同时包含 Sample_2 和 Sample_3。但是我在 File_2 中有 Sample_2,在 File_3 中有 Sample_3。类似地,我有一百多个文件作为输入。您的解决方案运行良好,因为我将所有文件添加为输入 f1 f2 f3 f4 .. 如果我将 sample_2 和 sample_3 拆分为不同的文件,您能否建议在代码中进行哪些更改以使其更简单?
  • 如果您有多个文件,我已经建议替换,替换后您可以输入通配符,如file1 sample*
【解决方案2】:

求解算法可以是:

  • 读取第一个文件并将数据存储在哈希中,样本名称为键,其余为数组数据
  • 将第二个文件作为记录读取,以空行作为记录分隔符
  • 将记录拆分为样本名称和数据数组
  • 以数组数据实体为键形成哈希并赋值1
  • 根据 Sample_1 数组中存在的元素将数据数组重新映射为 0 或 1
  • 将结果存储在样本哈希中
  • 输出样本名称和数据数组,用于按键排序的样本哈希的每个元素
use strict;
use warnings;
use feature 'say';

my $file_1 = 'sample_1.dat';
my $file_2 = 'samples.dat';
my $samples;

open my $fh, '<', $file_1
    or die "Couldn't open $file_1";
my ($name,@genome) = split(' ', <$fh>);
close $fh;

$samples->{$name} = \@genome;

{
    $/ = "\n\n";

    open $fh, '<', $file_2
        or die "Couldn't open $file_2";
        
    while( my $block = <$fh> ) {
        my($name,@genome) = split(' ', $block);
        my %hash;
        $hash{$_} = 1 for @genome;
        @genome = map{ $hash{$_} ? 1 : 0 } @{$samples->{Sample_1}};
        $samples->{$name} = \@genome;
    }

    close $fh;
}

for my $sample ( sort keys %$samples ) {
    say "$sample " . join("\t",@{$samples->{$sample}}) 
}

输出

Sample_1 23     45      46      67      78      47      98      73      87      45      97      21
Sample_2 1      0       0       1       0       1       0       0       1       0       1       0
Sample_3 0      0       0       1       1       0       1       0       0       0       0       1

【讨论】:

    【解决方案3】:

    awk 来救援!

    $ awk 'function pr() {for(i=2;i<=n;i++) printf "%s%d", OFS,(h[i] in p)+0; print ""}     
           NR==1  {n=split($0,h); print; next} 
           FNR==1 {if(f) pr(); delete p; printf "%s",$0} {f=1;p[$1]} 
           END    {pr()}' file1 file2 file3 | column -t
    
    Sample_1  23  45  46  67  78  47  98  73  87  45  97  21
    Sample_2  1   0   0   1   0   1   0   0   1   0   1   0
    Sample_3  0   0   0   1   1   0   1   0   0   0   0   1
    

    【讨论】:

    • 谢谢。这应该适用于多个文件,只是第一个文件由于结构而不同。
    • 谢谢。该解决方案完美运行
    猜你喜欢
    • 1970-01-01
    • 2011-02-12
    • 2014-04-23
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多