【问题标题】:Perl: Creating and manipulating hash of arrays for log-odds scores of DNA sequencesPerl:为 DNA 序列的对数得分创建和操作数组的散列
【发布时间】:2019-08-18 05:32:56
【问题描述】:

又是我。即使在查看文档之后,我也无法创建数组哈希。我希望 HoA 在 DNA 序列中包含基序(较小序列)的对数优势得分。我希望结构看起来像:

$HoA{$id}[$pos] = #score based on the position

$id 是序列 ID,$pos 是序列中基序开始的位置。我输入了一个包含 DNA 序列的 .txt 文件,格式如下:

>Sequence_1
TCAGAACCAGTTATAAATTTATCATTTCCTTCTCCACTCCT
>Sequence_2
CCCACGCAGCCGCCCTCCTCCCCGGTCACTGACTGGTCCTG
>Sequence_3
TCGACCCTCTGGAACCTATCAGGGACCACAGTCAGCCAGGCAAG

例如:序列 1 的位置 2 的基序是“AGA”。 以下是我到目前为止的代码(稍微简化了一点):

use strict;
use warnings;
use Data::Dumper; 

print "Please enter the filename of the fasta sequence data: ";
my $filename1 = <STDIN>;

#Remove newline from file
chomp $filename1;

#Open the file and store each dna seq in hash
my %HoA = ();
my %loscore = ();
my $id = '';
open (FILE, '<', $filename1) or die "Cannot open $filename1.",$!;
my $dna;
while (<FILE>)
{
    if($_ =~ /^>(.+)/)
    {
        $id = $1; #Stores 'Sequence 1' as the first $id, etc.
    }
    else
    {
        $HoA{$id} = [ split(//) ]; #Splits the contents to allow for position reference later
        $loscore{$id} .= 0; #Creates a hash with each id number to have a log-odds score (initial score 0)
        $maxscore{$id} .= -30; #Creates a hash with each id number to have a maxscore (initial score -30)
    }
}
close FILE;

my $width = 3;

my %logodds;  #I know there is a better way to do this - this is just for simplicity
$logodds{'A'}[0] = 0.1;
$logodds{'A'}[1] = 0.2;
$logodds{'A'}[2] = 0.3;
$logodds{'C'}[0] = 0.2;
$logodds{'C'}[1] = 0.5;
$logodds{'C'}[2] = 0.2;
$logodds{'G'}[0] = 0.3;
$logodds{'G'}[1] = 0.2;
$logodds{'G'}[2] = 0.4;
$logodds{'T'}[0] = 0.4;
$logodds{'T'}[1] = 0.1;
$logodds{'T'}[2] = 0.1;

print Dumper (\%logodds);
print "\n\n";
for my $base (qw( A C G T))
{
    print "logodds$base @{$logodds{$base}}\n";
}

my @arr;

foreach $id (keys %HoA)
{   
    for my $pos1 (0..length($HoA{$id})-$width-1)    #Look through all positions the motif can start at
    {
        for my $pos2 ($pos1..$pos1+($width-1)) #look through the positions at a specific motif starting point
        {
            for my $base (qw( A C G T))
            {
                if ($HoA{$id}[$pos2] eq $base)  #If the character matches a base:
                {
                    for my $pos3 (0..$width-1) #for the length of the motif:
                    {
                        $arr[$pos1] += $logodds{$base}[$pos3]; 
                        @{ $loscore{$id}} = @arr; #Throws error here
                    }
                }   
            }   
        }
    }
}
print Dumper(\%loscore);

我不断收到错误: 在第 75 行使用“strict refs”时,不能使用字符串(“0”)作为 ARRAY 引用。

我想要的具有此数据的对数赔率得分示例是:

$HoA{'Sequence 1'}[2] = 0.1 + 0.2 + 0.3 = 0.6

因此,在序列 1 中从位置 2 开始的基序“AGA”的对数几率得分为 0.6。感谢您的耐心和帮助!如果我需要澄清任何事情,请告诉我。

【问题讨论】:

  • 第75行是哪一个?
  • 声明:@{ $loscore{$id}} = @arr; 的行抛出错误
  • 之前你有 $loscore{$id} .= 0; 将一个数字附加到一个字符串有点奇怪 - 我会使用 "0",但 perl 会转换它以便它工作。不过,关键位是 %loscore 保存字符串,而不是数组引用。因此出现了这个错误。

标签: arrays perl hash


【解决方案1】:

我在您的代码中发现了一些问题。考虑以下几行:

$HoA{$id} = [ split(//) ];  # Splits the contents to allow for position reference later
$loscore{$id} .= 0;  # Creates a hash with each id number to have a log-odds score (initial score 0)
$maxscore{$id} .= -30;  # Creates a hash with each id number to have a maxscore (initial score -30)

根据您的 cmets,您似乎希望将 %loscore%maxscore 的条目初始化为 0 和 -30。但是,您使用的是 .= 运算符(附加字符串),而不是使用旧的 = 符号。我认为这不是您想要的,因此请考虑将 .= 更改为 =

(或者你可能打算改用//=。那样的话,如果%loscore%maxscore已经有一个$id条目,它不会被覆盖。但只有你可以肯定地说,如果你意味着使用//= 运算符。)

现在让我们看看$loscore{$id} = 0。这告诉我们%loscore 是一个散列(或“关联数组”),对于每个条目,它以 $id 作为键,以数字作为值。

但是,在您的代码的更下方,您会看到:

@{ $loscore{$id} } = @arr;

$loscore{$id}${ ... } 包裹的事实告诉我们%loscore 中的值是数组引用。但是我们已经在上面确定了它的值是数字!

因为您将数字视为数组引用,Perl 将其视为错误。

可能想要写的是:

@{ $HoA{$id} } = @arr;

由于 %HoA 散列的值包含数组引用,因此您希望将 that 作为数组取消引用。

【讨论】:

  • 感谢您的帮助!再看一遍,我想我想用数组的三个哈希:%HoA, %loscore, %maxscore。如果我希望%loscore 中的每个初始值都为0%maxscore 中的每个初始值都为-30,您对创建这两个数组哈希有什么建议吗?
  • 我目前正在尝试map 来做这件事。
  • 如果要将%loscore%maxscore的每一项初始化为0和-30,那么它们一定不能是“数组哈希”。相反,它们将是“数字哈希”。换句话说,如果您有一个将数组引用保存为值的哈希(使其成为“数组哈希”),则不能让它保存数字作为其值。也许您的意图是将%loscore 初始化为$loscore{$id} = [ 0 ];。这样%loscore 确实是一个“数组哈希”,其中数组将数字作为其元素。
  • 再看你的代码,我想当你写$loscore{$id} .= 0;时你意思是push @{ $loscore{$id} }, 0;。 (而当你写$maxscore{$id} .= 0; 时,你的意思是写push @{ $maxscore{$id} }, -30;。)这个更改会将0(或-30)附加到%loscore 中恰好是一个数组的值。也许这就是你想要的?
  • 您建议的push 方法最接近我想要的。是的,我想要一个与每个 $id 相关联的数字,就像你说的那样,但我想要每个 $id 中有多个数字。所以$loscore{$id} 会有多个分数,可以通过被引用的数组中的位置来访问。
【解决方案2】:

我认为这可以解决问题: 替换

$loscore{$id} .= 0; $maxscore{$id} .= -30;

foreach $id (keys %HoA)
    {
        for my $len (0..(length($HoA{$id})-$width-1))
        {
            push @{ $loscore{$id} }, 0;
            push @{ $maxscore{$id} }, -30;
        }
    }

如果你有什么要补充的,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 2012-08-03
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 2014-05-19
    相关资源
    最近更新 更多