【问题标题】:Perl: Compare Values of 2 Files & Print Values of 2nd File which fall in a particular range of values from 1st filePerl:比较 2 个文件的值并打印第 2 个文件的值,这些值位于第一个文件的特定值范围内
【发布时间】:2013-02-22 12:34:46
【问题描述】:

我遇到了一个小故障。我有 2 个文件,如下所示:

文件1

chr10   179423  181499  181423  2076    +   NM_001202464    ZMYND11
chr10   693887  696118  695887  2231    +   NR_027151   C10orf108
chr10   694016  696382  696016  2366    +   NR_027152   C10orf108
chr10   1032348 1034467 1034348 2119    +   NM_012341   GTPBP4
chr10   1203707 1205930 1205707 2223    +   NR_015376   LINC00200

文件2

chr10   176225
chr10   180990
chr10   181315
chr10   181529
chr10   181695
chr10   182183
chr10   686673
chr10   686699
chr10   688273
chr10   695323
chr10   698323
chr10   722737
chr10   906075
chr10   908409
chr10   928052
chr10   950429
chr10   989722
chr10   1006348
chr10   1010731
chr10   1020229
chr10   1034526
chr10   1064089
chr10   1103000
chr10   1103198
chr10   1103267
chr10   1114980
chr10   1135327
chr10   1150625
chr10   1193412
chr10   1193677
chr10   1199817
chr10   1212181
chr10   1212310
chr10   1216875
chr10   1218919
chr10   1226134
chr10   1226254

需要什么

逐行,对于来自File1 的每个4th element,打印出来自File2 的值>= 2nd element from file1 & <= (4th element from file1+2000)

例如,在File1 中,row1 中的第 4 个元素是 181423。从File2 来看,>= 2nd element from file1(179423)<= 4th element from file1+2000(183423) 的值为 18090,181315,181529,181695,182183。

如果没有找到值,应该打印NA

期望的输出

一个制表符分隔的文件,如下所示:

chr10   179423  181423  183423  NM_001202464    ZMYND11     180990
                                                            181315
                                                            181529
                                                            181695
                                                            182183
chr10   693887  695887  697887  NR_027151   C10orf108       695323
chr10   694016  696016  698016  NR_027152   C10orf108       695323
chr10   1032348 1034348 1036348 NM_012341   GTPBP4          1034526
chr10   1203707 1205707 1207707 NR_015376   LINC00200       NA  

我的代码

我完全不知道如何去做。最初,我被告知我只需要从 file2 中找到位于 file12nd4th 元素之间的那些值。为此,我使用哈希编写了以下代码,虽然可以工作,但并没有完成完整的工作。 (if 循环中的&& 部分并没有按照我的预期进行,因此正在打印所有更大的值)

现在这段代码完全没用了:/我束手无策,因为我不知道在 Perl 编程的 3 个月内,我是否应该能够编写狡猾的程序。

use 5.014;
use warnings;

#Assign filenames
my $file1 = 'file1.txt' || die $!; #File with TSS coordinates
my $file2 = 'file2.txt' || die $!; #File with G4 coordinates

#Open files
open my $fh1, '<' , $file1 || die $!;
open my $fh2, '<' , $file2 || die $!;

#Open output
open OUT, ">G4_coordinates_promoters$file1.out" || die $!;

#Read files
while (<$fh1>) {
    chomp;
    my %data1; #Hash for TSS
    my ($key1, $val1) = (split) [1,3];
    $data1{$key1} = $val1;
    while (<$fh2>) {
        chomp ;
        my %data2; #Hash for G4 coordinates
        my ($key2, $val2) = (split) [1,2];
        $data2{$key2} = $val2;

        #Compare hashes
        if ( ($key2 > $key1) && 
             ($key2 << $data1{$key1})){ #Here the code after && is NOT working
            say OUT $key2
        }
    }
} 

感谢您解决我的问题。如果能找到一些直接的方法来解决这个问题,我将不胜感激。

【问题讨论】:

  • 我怀疑您不打算在$key2 &lt;&lt; $data1{$key1} 中使用左移运算符&lt;&lt;
  • @Neal:TLP 告诉您,|| 在此代码中不能代替 or。您的程序已损坏,die 语句将永远不会发生,因此它们无济于事。
  • @Neal 不,从不使用 die 语句,除非您更改代码以插入 0 或空字符串作为文件名。插入括号以强调优先级的 open 语句如下所示:open my $fh1, '&lt;' , ($file1 || die $!)
  • @Neal 这是一个难以检测的错误。 perldoc perlop 具有优先级表。可以看到||高于逗号,,但or低于。
  • @TLP 我认为自己很幸运能找到这样一个地方,那里有像你这样的老手来指导像我这样的新手。在没有现实世界的老师的情况下,这是我真正可以学到好东西的地方!

标签: perl hash bioinformatics


【解决方案1】:

这个程序似乎可以满足您的需求。

输出以制表符分隔格式写入 - 与您的输入数据相同 - 因此后续行具有正确数量的制表符,但与初始行没有物理对齐。如果您想要不同的东西,请说出来。

file2 中的所有值都被拉入数组@file2 并从那里处理。代码假定值已经排序。

while (<$fh>) {
  chomp;
  my @fields = split /\t/;

  my $min = $fields[1];
  my $max = $fields[3] + 2000;

  my @values;
  for my $val (@file2) {
    last if $val > $max;
    push @values, $val if $val >= $min;
  }
  push @values, 'NA' unless @values;

  for my $val (@values) {
    print join("\t", @fields, $val), "\n";
    $_ = '' for @fields;
  }
}

输出

chr10 179423  181499  181423  2076  + NM_001202464  ZMYND11 180990
                181315
                181529
                181695
                182183
chr10 693887  696118  695887  2231  + NR_027151 C10orf108 695323
chr10 694016  696382  696016  2366  + NR_027152 C10orf108 695323
chr10 1032348 1034467 1034348 2119  + NM_012341 GTPBP4  1034526
chr10 1203707 1205930 1205707 2223  + NR_015376 LINC00200 NA

【讨论】:

  • 您好,先生!再次感谢您提供简单的方法。只需再进行一项修改。我需要为那些找不到值的条目打印NA。我该怎么做?
  • 如果我对这行代码的理解正确,$_ = '' for @fields;'' 会在找到多个值时放置一个空行?
  • 我已根据您的新要求修改了答案。 $_ = '' for @fields 将所有字段设置为一个空字符串,这样这些值就不会打印在多于一行(但正确数量的标签 输出)。
  • 非常感谢先生!我真希望有一天我也能像你一样写程序!我真的很喜欢你简单、直接的风格。我希望我有你做我的老师:)
猜你喜欢
  • 2021-10-11
  • 1970-01-01
  • 2014-07-06
  • 2016-02-05
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多