当推送值时,HoHOA的行为不同

时间:2013-10-07 15:03:11

标签: arrays perl data-structures hash

我有以下数据:

eya XLOC_000445_Change:10.3_q:0.003 atonal1
six XLOC_00099_Change:70.0_q:0.095  atonal1
six-eya XLOC_0234324_Change:19.8_q:0.05 atonal1
eya XLOC_00010_Change:6.5_q:0.22    c-myc
six XLOC_025437_Change:1.1_q:0.018  c-myc
six-eya XLOC_001045_Change:2.3_q:0.0001 c-myc
eya XLOC_000115_Change:7.3_q:0.03   ezrin
six XLOC_000001_Change:7.9_q:0.00006    ezrin
six-eya XLOC_0234322_Change:9.0_q:0.0225    ezrin
six-eya XLOC_091345_Change:9.3_q:0.005  slc12a2
eya XLOC_000445_Change:9.9_q:0.3    atonal1
six XLOC_00099_Change:7.0_q:0.95    atonal1
six-eya XLOC_0234324_Change:9.8_q:0.5   atonal1

并尝试过如下构建HoHoA:

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

方法1:将数组值推送到HoH:

while (<$input>) { 
    chomp;
    push @xloc, $1 if ($_ =~ /(XLOC_\d+)/);
    push @change_val, $1 if ($_ =~ /Change:(-?\d+\.\d+|-?inf)/);
    push @q_value, $1 if ($_ =~ /q:(\d+\.\d+)/);
    my @split = split('\t');            
    push @condition, $split[0];
    push @gene, $split[2];
}           
push @{ $experiment{$gene[$_]}{$condition[$_]} }, [ $xloc[$_], $change_val[$_], $q_value[$_] ] for 0 .. $#change_val;

方法2:即时为HoHoA分配值:

while (<$input>) { 
    chomp;
    my $xloc = $1 if ($_ =~ /(XLOC_\d+)/);
    my $change = $1 if ($_ =~ /Change:(-?\d+\.\d+|-?inf)/);
    my $q_value = $1 if ($_ =~ /q:(\d+\.\d+)/);
    my @split = split('\t');
    my $condition = $split[0];
    my $gene = $split[2];
    $experiment{$gene}{$condition} = [ $xloc, $change, $q_value ];
}

两者都很好 - 只要我得到了我想要的数据结构。然而,只有第一种方法(推动)确保以重复形式存在的基因(在这种情况下为atonal1)在HoHoA中表示两次。

我的下游代码最初用于处理以第二种方式构建的HoHoA,我不能为我的生活解决为什么在以下代码中处理两种方法的方式不同:

下游代码:

my (%change, %seen, $xloc, $change_val, $q_value);
for my $gene (sort keys %experiment) {
     for my $condition (sort keys %{$experiment{$gene}}) {
         $seen{$gene}++; # Counts for each occurrence of gene 
         if ( (not exists $change{$gene}) || (abs $change{$gene} < abs $experiment{$gene}{$condition}[1]) ) { # Has a larger change value
             $change{$gene} = $experiment{$gene}{$condition}[1];
         }               
    }
}
print Dumper \%change;

当我在任何一种方法上运行上述代码时,我得到:

方法1的输出

$VAR1 = {
          'atonal1' => [
                         'XLOC_0234324',
                         '9.8',
                         '0.5'
                       ],
          'c-myc' => undef,
          'ezrin' => undef,
          'slc12a2' => undef,
        };

方法2的输出

$VAR1 = {
          'atonal1' => '9.9', # i.e. the largest change value for each condition/gene
          'c-myc' => '6.5',
          'ezrin' => '9.0',
          'slc12a2' => '9.3',
        };

我想要的是:

$VAR1 = {
          'atonal1' => [
                          '9.9',
                          '70.0' # This is the difference - i.e the both values are added to the hash `%change`
                       ], 
          'c-myc' => '6.5',
          'ezrin' => '9.0',
          'slc12a2' => '9.3',
        };

我不知道是什么造成了差异

更新

在使用方法1 推送值后,我会发布%experiment的转储输出:

$VAR1 = {
          'atonal1' => {
                         'eya' => [
                                    [
                                      'XLOC_000445',
                                      '10.3',
                                      '0.003'
                                    ],
                                    [
                                      'XLOC_000445',
                                      '9.9',
                                      '0.3'
                                    ]
                                  ],
                         'six' => [
                                    [
                                      'XLOC_00099',
                                      '70.0',
                                      '0.095'
                                    ],
                                    [
                                      'XLOC_00099',
                                      '7.0',
                                      '0.95'
                                    ]
                                  ],
                         'six-eya' => [
                                        [
                                          'XLOC_0234324',
                                          '19.8',
                                          '0.05'
                                        ],
                                        [
                                          'XLOC_0234324',
                                          '9.8',
                                          '0.5'
                                        ]
                                      ]
                       },
          'c-myc' => {
                       'eya' => [
                                  [
                                    'XLOC_00010',
                                    '6.5',
                                    '0.22'
                                  ]
                                ],
                       'six' => [
                                  [
                                    'XLOC_025437',
                                    '1.1',
                                    '0.018'
                                  ]
                                ],
                       'six-eya' => [
                                      [
                                        'XLOC_001045',
                                        '2.3',
                                        '0.0001'
                                      ]
                                    ]
                     },

          'ezrin' => {
                       'eya' => [
                                  [
                                    'XLOC_000115',
                                    '7.3',
                                    '0.03'
                                  ]
                                ],
                       'six' => [
                                  [
                                    'XLOC_000001',
                                    '7.9',
                                    '0.00006'
                                  ]
                                ],
                       'six-eya' => [
                                      [
                                        'XLOC_0234322',
                                        '9.0',
                                        '0.0225'
                                      ]
                                    ]
                     },
          'slc12a2' => {
                         'six-eya' => [
                                        [
                                          'XLOC_091345',
                                          '9.3',
                                          '0.005'
                                        ]
                                      ]
                       },

        };

1 个答案:

答案 0 :(得分:4)

让我们把你的数据重新格式化一下。我不是说这是您格式化数据所需的方式。我只是这样做,以便更好地理解它代表什么:

GENE      XLOC                  CHANGE   Q VALUE   CONDITION
========  ====================  =======  ========  ==========
eya       XLOC_000445_Change:   10.3_q:  0.003     atonal1
six       XLOC_00099_Change:    70.0_q:  0.095     atonal1
six-eya   XLOC_0234324_Change:  19.8_q:  0.05      atonal1
eya       XLOC_00010_Change:    6.5_q:   0.22      c-myc
six       XLOC_025437_Change:   1.1_q:   0.018     c-myc
six-eya   XLOC_001045_Change:   2.3_q:   0.0001    c-myc
eya       XLOC_000115_Change:   7.3_q:   0.03      ezrin
six       XLOC_000001_Change:   7.9_q:   0.00006   ezrin
six-eya   XLOC_0234322_Change:  9.0_q:   0.0225    ezrin
six-eya   XLOC_091345_Change:   9.3_q:   0.005     slc12a2
eya       XLOC_000445_Change:   9.9_q:   0.3       atonal1
six       XLOC_00099_Change:    7.0_q:   0.95      atonal1
six-eya   XLOC_0234324_Change:  9.8_q:   0.5       atonal1

我的专栏假设是否正确?

首先,我建议您使用split来分割您的值而不是正则表达式。这是逐行完成的。 Perl在优化方面非常有效。 90%的编程都是调试和支持您的程序。通过将多个步骤压缩成一个步骤来提高效率只会让事情变得更难以理解,而优化中返回的值非常小。

让我们走每一行,并将其分解出来:

while ( my $line = <$input> ) {
    chomp $line;
    my ( $gene, $more_data, $condition ) = split /\s+/, $line;

此时:

$gene = 'eye'
$more_data = 'XLOC_000445_Change:10.3_q:0.003';
$condition = 'atonal1`    # I'm not sure what this is...

现在,我们可以拆分$more_data

my ( $xloc, $change, $q_value ) = split /:/, $more_data;
$xloc =~ s/^XLOC_//;
$change =~ s/_q$//;

现在我们有:

$xloc = '000445';
$change = '10.3';
$q_value = '0.003';

这更有意义吗?

您的一个问题是,您试图将数据存储在一个非常复杂的结构中,而不是真正考虑数据所代表的内容。

假设你的数据是这样的:

  • 基因可能包含多个条件
  • 每个基因条件组合可以有结果
  • 此结果包含 xloc q_value 更改

这意味着您的数据应如下所示:

$experiment{$gene}->{$condition}->{XLOC}    = $xloc;
$experiment{$gene}->{$condition}->{Q_VALUE} = $q_value;
$experiment{$gene}->{$condition}->{CHANGE}  = $change;

但是,我在列表中看到了两次gene = eya,condition = atonal1。也许你还需要更多的东西:

  • 基因可能包含多个条件
  • 每个基因条件组合可以有多个结果
  • 每个结果都包含 xloc q_value 更改

如果是这种情况,您的数据结构应如下所示:

$experment{$gene}->{$condition}->[0]->{XLOC}    = $xloc;
$experment{$gene}->{$condition}->[0]->{Q_VALUE} = $q_value;
$experment{$gene}->{$condition}->[0]->{CHANGE}  = $change;

这不是答案。我只是试图了解您的数据是什么以及您要在该数据中存储的内容。一旦我们解决了这个问题,我可以帮助您完成剩余的计划。

如果我对您的数据所代表的内容的理解是准确的,请告诉我。在此答案中添加评论,并稍微更新您的问题。

一旦我知道自己走上了正轨,我将向您展示如何更轻松地管理此结构并跟踪其中的所有内容。

现在我知道自己走在了正确的轨道上,解决方案非常简单:面向对象编程!

让我解释一下:每个实验都包含一个基因条件对。这就是我实验的关键。

我为每个Gene-Condition对创建了一个Local::Condition。在此我存储了我的结果数组。

我的结果包含三个项目。


看哪:答案!

我决定做的是创建一个结果对象。该对象包含该结果的XLoc,Change和Q Value。通过将我的结果打包成一个对象,我尝试跟踪它的问题就更少了。

所以我们拥有的是:

  • 我们有实验
  • 每个_experiment都由一个基因/条件对组成,我们对其进行了实验。
  • 每个基因/条件实验都包含一系列结果。

现在,跟踪正在发生的事情要容易得多。对于每一行,我创建一个Local::Result类型的对象,其中包含该基因/条件对的结果集

所以,我所要做的就是将我的结果推送到代表我的结果集的基因/条件数组

#
# Create a Result for this experiment
#

my $result = Local::Result->new( $xloc, $change, $q_value );

#
# Push this result onto your $gene/condition experiment
#
push @{ $experiments{$gene}->{$condition} }, $result;

请注意我的语法非常明确。我有一个名为%experiments的哈希,由 Genes 键入。每个基因都包含该基因的条件。此基因/条件对是结果的数组。

面向对象的语法可能有点复杂,但Perl文档中有一个很好的tutorial。通过使用面向对象的编程,您可以将必须​​跟踪的详细信息组合在一起。

#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use autodie;
use Data::Dumper;

my %experiments;

while ( my $line = <DATA> ) {
    my ($condition, $more_data, $gene) = split /\s+/, $line;

    my ($xloc, $change, $q_value) = split /:/, $more_data;
    $xloc   =~ s/^XLOC_(.*)_Change/$1/;
    $change =~ s/_q$//;

    my $result = Local::Result->new( $xloc, $change, $q_value );
    push @{ $experiments{$gene}->{$condition} }, $result;
}

printf "%-10.10s  %-10.10s  %10.10s  %-4s  %-7s\n\n",
    "Gene", "Condition", "XLoc", "Chng", "Q Value";
for my $gene ( sort keys %experiments ) {
    for my $condition ( sort keys %{ $experiments{$gene} } ) {
        for my $result ( @{ $experiments{$gene}->{$condition} } ) {
            printf "%-10.10s  %-10.10s  %10.10s  %-4.1f  %-7.1f\n",
                $gene, $condition, $result->xloc, $result->change, $result->q_value;
        }
    }
}

package Local::Result;

sub new {
    my $class       = shift;
    my $xloc        = shift;
    my $change      = shift;
    my $q_value     = shift;

    my $self        = {};
    bless $self, $class;

    $self->xloc($xloc);
    $self->change($change);
    $self->q_value($q_value);

    return $self;
}

sub xloc {
    my $self        = shift;
    my $xloc        = shift;

    if ( defined $xloc ) {
        $self->{XLOC} = $xloc;
    }
    return $self->{XLOC};
}

sub change {
    my $self        = shift;
    my $change      = shift;

    if ( defined $change ) {
        $self->{CHANGE} = $change;
    }
    return $self->{CHANGE};
}

sub q_value {
    my $self        = shift;
    my $q_value     = shift;

    if ( defined $q_value ) {
        $self->{Q_VALUE} = $q_value;
    }
    return $self->{Q_VALUE};
}

package main;


__DATA__
eya XLOC_000445_Change:10.3_q:0.003 atonal1
six XLOC_00099_Change:70.0_q:0.095  atonal1
six-eya XLOC_0234324_Change:19.8_q:0.05 atonal1
eya XLOC_00010_Change:6.5_q:0.22    c-myc
six XLOC_025437_Change:1.1_q:0.018  c-myc
six-eya XLOC_001045_Change:2.3_q:0.0001 c-myc
eya XLOC_000115_Change:7.3_q:0.03   ezrin
six XLOC_000001_Change:7.9_q:0.00006    ezrin
six-eya XLOC_0234322_Change:9.0_q:0.0225    ezrin
six-eya XLOC_091345_Change:9.3_q:0.005  slc12a2
eya XLOC_000445_Change:9.9_q:0.3    atonal1
six XLOC_00099_Change:7.0_q:0.95    atonal1
six-eya XLOC_0234324_Change:9.8_q:0.5   atonal1