2

我是 Perl 和一般编程的绝对新手(不到一个月的经验)。

如果我要解决更大的问题,我会遇到一个需要解决的问题。

基本上,我有 2 个数组,如下所示:

@array1 = ('NM_1234' , '1452' , 'NM_345' , '5008' , 'NR_6145' , '256');
@array2 = ('NM_5673' , '2' , 'NM_345' , '5' , 'NR_6145' , '10');

@array1包含 id 编号,后跟长度。id 号是核苷酸序列,长度是序列的长度。

@array2包含 id 编号,后跟 G-Quadruplex 结构的数量,因此一些序列仅包含 2 个此类结构,而其他序列包含 10 个或更多。

基本问题是,我需要为每个匹配的 ID 号添加(例如 5008、256)@array2中的“长度数字” 。@array1

因此,例如NM_345在两个数组中都匹配,我需要向它添加5008,以便最终结果变为NM_345,5,5008

NR_6145和其他此类匹配类似(有超过 20,000 个 ID 号码@array2

到目前为止,我已经能够编写可以在两个数组中搜索相同 id 号的代码。这是代码:

#Enter file name
print "Enter file name: ";
$in =<>;
chomp $in;

open(FASTA,"$in") or die;

@data = <FASTA>; #Read in data        
$data = join ('',@data); #Convert to string
@data2 = split('\n',$data); #Explode along newlines

#Enter 2nd file name
print "\n\nEnter 2nd file name: ";
$in2=<>;
chomp $in2;

open(FASTA,"$in2") or die;
@entry =<FASTA>; #Read in data

$entry = join('',@entry); #Convert to string
@entry2 = split('\n',$entry); #Explode along newlines

my %seen;
for  $item (@data2) {
    if($item =~ /([0-9]+)/){
        push @{$seen{$key}}, $item;#WHAT IS THIS DOING? HOW?
    }
}

for my $item (@entry2) {
    if ($item =~ /([0-9]+)/){
        if (exists $seen{$key}) {
            print $item,"\n";
        };        
    }
}
exit;

我从这里的解决方案中派生了从 2 个数组中找到相同元素的代码,因此完全归功于 Chas.Owens:https ://stackoverflow.com/a/1064929/1468737 。当然,我还不太了解这部分:

push @{$seen{$key}}, $item;#WHAT IS THIS DOING? HOW?

它似乎是一个哈希值的数组或什么的?

那么,现在如何将 @array1 中的长度元素添加到 @array2 中?我需要使用我认为的拼接命令,但是如何?

我想要的输出应该是这样的:

NM_345,5,5008 <br>
NM_6145,10,256<br>
etc

我还需要将此输出保存到一个文件中,然后再对其进行分析,以查看长度和 G-quadruplex 数之间是否存在任何相关性。

任何帮助或输入将不胜感激。

感谢您花时间解决我的问题!


编辑:这个编辑是为了显示数据文件的样子。它们基本上是来自我编写的其他程序的 putput 文件。

我的第一个文件名为 Transcriptlength.fa,其中包含超过 40,000 个 ID 号码,@array1如下所示:

NR_037701
3353

NM_198399
2414

NR_026816
601

NR_027917
658

NR_002777
1278

我的第二个文件名为 Quadcount.AllGtranscripts.fa,其中包含超过 20,000 个 id 数字@array2,如下所示:

NM_000014   
1

NM_000016   
3

NM_000017   
19

NM_000018   
2

NM_000019   
3

NM_000020   
30

NM_000021   
1

NM_000022   
2

NM_000023   
5

NM_000024   
1

NM_000025   
15

NM_000029   
5
4

4 回答 4

1

一个问题的问题太多了......但无论如何我们都要走了:

push @{$seen{$key}}, $item;

%seen是一个散列(或关联数组),因此从与该 key 关联的值中$seen{$key}恢复。然后将此值视为数组引用并通过使用运算符转换为数组。finally被添加到这个数组的末尾。%seen$key@{}$item

我不明白你所说的长度是什么意思......你的意思是前面的数组长度?

要将其保存在文件中,您只需要print()在脚本中执行脚本时重定向到文件,例如:

./my_perl_script.pl > my_output_file

文件输入也是如此,你真的不需要open()close()等等。这更灵活,编码更快:

./my_perl_script.pl < my_input_file

这允许您以更简单的方式进行管道传输,并将数据从/传递到其他脚本/进程。当然,两种重定向可以同时使用:

./my_perl_script.pl < my_input_file > my_output_file

此外,您甚至不需要保存到文件中(无论如何,拥有已处理数据的副本总是明智的)并且您可以将结果直接通过管道传输到其他进程,例如

./my_perl_script.pl | my_other_script

这适用于我使用过的所有操作系统(Windows、Linux、OS X、BSD)。

于 2012-06-20T15:55:30.693 回答
1

看起来您在读取数据文件以及生成所需的输出时遇到了麻烦。除非您向我们展示文件数据的示例,否则我们无法帮助解决这部分问题,但这里有一个正确生成输出的解决方案。

最好将数据存储在散列中,因为这样可以直接访问给定序列 ID 的长度和结构计数。幸运的是,您所描述的数组可以通过简单的赋值轻松转换为哈希,因此这个简短的程序可以从您显示的数组中完成您想要的操作。

grep /\D/, @array2循环中的列表仅@array2通过仅选择那些包含非十进制字符的元素来从中选择所有序列 ID。我已经这样做了,以防序列显示的顺序很重要。在您的最终程序中,您可能应该直接从文件中处理数据,而不是将其读入数组,因此这不会成为问题。

use strict;
use warnings;

my @array1 = ( NM_1234 1452   NM_345 5008   NR_6145 256 );
my @array2 = ( NM_5673    2   NM_345    5   NR_6145  10 );

my %lengths = @array1;
my %counts = @array2;

for my $id (grep /\D/, @array2) {
  my $length = $lengths{$id};
  printf "%s,%s,%s\n", $id, $length, $counts{$id} if $length;
}

输出

NM_345,5008,5
NR_6145,256,10

更新

您的文件数据非常适合设置段落模式,其中记录在数据文件中由空行分隔。为此,您将输入记录分隔符变量$/设置为空字符串""

这个修改后的程序从第一个文件中读取记录,将它们拆分为空白(空白包括空格、制表符和换行符等),并构建一个%lengths将每个序列 ID 与其长度相关联的哈希。

对第二个文件执行相同的操作,这次检查序列 ID 是否出现在哈希中。如果是这样,则输出完整的记录。

use strict;
use warnings;

my $fh;
my %lengths;

$/ = "";

open $fh, '<', 'Transcriptlength.fa'
    or die qq(Unable to open "Transcriptlength.fa": $!);

while (<$fh>) {

  my ($id, $length) = split;
  next unless $id;

  $lengths{$id} = $length;
}

open $fh, '<', 'Quadcount.AllGtranscripts.fa'
    or die qq(Unable to open "Quadcount.AllGtranscripts.fa": $!);

while (<$fh>) {

  my ($id, $count) = split;
  next unless $id;

  my $length = $lengths{$id};
  next unless $length;

  print join(',', $id, $count, $length), "\n";
}

不幸的是,您选择的样本数据不包含匹配的序列 ID,因此在针对该数据运行时,该程序没有输出。您的实际文件将更有效率。

于 2012-06-20T23:57:06.377 回答
0

更新:我留下原始答案代码的链接来说明抽象不同子任务(尤其是处理子任务)的概念。但是,如果您确定输入文件中的内容,您的问题可以更容易地解决:

use warnings;
use strict;

my $lengths_filename = 'Transcriptlength.fa';
my $counts_filename  = 'Quadcount.AllGtranscripts.fa';

my %sequence;   # it will be the basic data repository

local $/ = ''; 
# ...by this we ensure that files will be read by logical blocks instead of lines. 
# Might need some tweaking, if 'empty line' in your sample is not really empty.

# we start processing from 'counts' file, as only those records present in it
# should actually be in our output:
open my $cfh, '<', $counts_filename 
  or die $!, "\n";
while (<$cfh>) {
  # each logical block consists of two parts, divided by whitespace
  my ($name, $count) = split; 

  # here goes magic: we simultaneously create a new record in our repository...
  # ... and set its 'count' property to the value, extracted from the scanned fileblock
  $sequence{$name}{count} = $count;
}
close $cfh;

# now we go for lengths, approach is almost the same
open my $lfh, '<', $lengths_filename or die $!, "\n";
while (<$lfh>) {
  my ($name, $length) = split;

  # here we check that the sequence was in 'counts' file
  if (exists $sequence{$name}) { 
    $sequence{$name}{length} = $length;
  } 
}
close $lfh;

# and now the output block: it's mostly the same as in the original answer:
for my $name (sort keys %sequence) {
  print "$name, $sequence{$name}{count}, $sequence{$name}{length}", "\n";
}

这是另一个键盘来说明它是如何工作的。不要介意奇怪__DATA__的东西,它只是针对这个特定版本的程序(使用__DATA__部分允许我模拟从文件中读取,因为我不能在键盘上使用外部源)。

于 2012-06-20T16:30:15.343 回答
0

这个

$data = join ('',@data); #转换成字符串
@data2 = split('\n',$data); #沿换行符爆炸

不会像您想象的那样创建您的数组。它只是重新创建了您开始使用的线条结构。我认为你的意思是用“,”逗号分开。使用调试工具。至少插入一个这样的打印块

打印连接(“:”,@data2);

看看你的数组中实际有什么。

在继续下一条之前,让每条线都正常工作。然后,如果您无法弄清楚为什么某条线路无法正常工作,您可以在此处发布问题。

事实上,很难用代码说出你想在代码中说什么,因为这些想法是不完整的。

于 2012-06-20T16:53:20.423 回答