免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3440 | 回复: 8
打印 上一主题 下一主题

求各位大神,perl 对特定范围内的数据求平均值 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-08-17 16:17 |只看该作者 |倒序浏览
文件为:
Chr        Pos        Y
1        49820        -1.68855
1        54414        -1.55555
1        99585        -1.05338
1        103929        -0.523771
1        124119        -0.261121
1        200009        -0.1234
1        390189        2.2456
2        48625        0.0250024
2        88663        -0.659643
2        90128        -0.302134
2        122780        -0.366919
2        555583        -1.00859
想根据第一列和第二列的范围来求第三列的平均值,具体为:第二列的按照每100,000的长度来分组,把第三列求一个平均值,如果有些范围没有数值则写为0(如下)。想得到的结果是:
1  100,000    -1.432493333
1  200,000    -0.392446
1  300,000    -0.1234
1  400,000    2.2456
2  100,000    -0.3259234
2  200,000    0
2  300,000    0
2  400,000    0
2  500,000    0
2  600,000    -1.00859
其中100,000、200,000...代表0-100,000、100,000-200,000范围的意思。
求各位大神帮忙啦!

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
2 [报告]
发表于 2016-08-19 11:29 |只看该作者
有些地方没有看懂, 问下
1  100,000    -1.432493333
1  200,000    -0.392446
1  300,000    -0.1234
以上的三个值如何的来的吗? 简单说就是不明白求值的公式!

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
3 [报告]
发表于 2016-08-19 14:54 |只看该作者
$ perl -lane 'BEGIN{$r=100000}sub Out{$_[1]=$_[1]*$r+$r;print join"\t",@_;$avg=$Y=$c=0}sub avg{if($c){$avg=$Y/$c};if($F[0]!=$C){if($Y){Out($C,$P,$avg)}$C=$F[0]}$Pn=int($F[1]/$r);for($P..$Pn-1){Out($C,$_,$avg);++$P}$Y+=$F[2];$P=int($F[1]/$r);++$c}{if($.>1){avg();$C=$F[0]}}END{Out($C,$P,$Y/$c)}' FILE
1        100000        -1.43249333333333
1        200000        -0.392446
1        300000        -0.1234
1        400000        2.2456
2        100000        -0.3122582
2        200000        -0.366919
2        300000        0
2        400000        0
2        500000        0
2        600000        -1.00859

论坛徽章:
6
丑牛
日期:2014-03-21 15:42:04子鼠
日期:2014-04-12 11:50:17处女座
日期:2014-09-01 09:25:1115-16赛季CBA联赛之吉林
日期:2015-12-22 14:01:5215-16赛季CBA联赛之广东
日期:2016-03-08 18:49:422016科比退役纪念章
日期:2016-07-06 12:19:55
4 [报告]
发表于 2016-08-19 16:42 |只看该作者
本帖最后由 stanley_tam 于 2016-08-19 17:06 编辑

来个非one liner的
不是很符合要求(如果有些范围没有数值则写为0)
  1. #!perl
  2. package Pos;
  3. use strict;
  4. use warnings;

  5. sub new {
  6.     my ($class, $chr, $pos, $Y) = @_;
  7.     my $self = bless {}, $class;

  8.     $self->{'pos'}   = $pos;
  9.     $self->{'chr'}   = $chr;
  10.     $self->{'Y'  }   = $Y;
  11.     $self->{'scope'} = $self->get_scope;

  12.     return $self;
  13. }

  14. sub get_scope {
  15.     my ($self) = @_;
  16.     my $pos    = $self->{'pos'};
  17.     return int($pos / 100_000 + 1) * 100_000;
  18. }

  19. 1;

  20. package main;
  21. use strict;
  22. use autodie qw{ open close };
  23. use List::Util qw{ sum };

  24. sub main;
  25. sub load_data;
  26. sub calculate_mean_value;

  27. main();

  28. sub main {
  29.     my $file = 'data.txt';
  30.     my $data_href = load_data($file);
  31.     for my $chr ( sort keys %{$data_href} ){
  32.         for my $scope (sort keys %{$data_href->{$chr}}){
  33.             my $Y_aref = $data_href->{$chr}->{$scope};  
  34.             my $mean_value = calculate_mean_value($Y_aref);
  35.             print "$chr $scope $mean_value$/";
  36.         }
  37.     }
  38. }

  39. sub load_data {
  40.     my ($file) = @_;
  41.     my $data_href = +{};

  42.     my @pos_collection = ();

  43.     open my $fh, '<', $file;

  44.     # skip header
  45.     readline $fh;
  46.     while (defined(my $line = readline $fh)) {
  47.         chomp $line;
  48.         next if not $line;

  49.         my ($chr, $pos, $Y) = split /\s+/, $line;
  50.         my $scope = Pos->new($chr, $pos, $Y)->get_scope;
  51.         push @{ $data_href->{$chr}->{$scope} }, $Y;
  52.     }

  53.     close $fh;

  54.     return $data_href;
  55. }

  56. sub calculate_mean_value {
  57.     my ($aref) = @_;
  58.     return sum( @{$aref} ) / ++$#$aref;
  59. }

  60. __END__
复制代码

论坛徽章:
95
程序设计版块每日发帖之星
日期:2015-09-05 06:20:00程序设计版块每日发帖之星
日期:2015-09-17 06:20:00程序设计版块每日发帖之星
日期:2015-09-18 06:20:002015亚冠之阿尔艾因
日期:2015-09-18 10:35:08月度论坛发贴之星
日期:2015-09-30 22:25:002015亚冠之阿尔沙巴布
日期:2015-10-03 08:57:39程序设计版块每日发帖之星
日期:2015-10-05 06:20:00每日论坛发贴之星
日期:2015-10-05 06:20:002015年亚冠纪念徽章
日期:2015-10-06 10:06:482015亚冠之塔什干棉农
日期:2015-10-19 19:43:35程序设计版块每日发帖之星
日期:2015-10-21 06:20:00每日论坛发贴之星
日期:2015-09-14 06:20:00
5 [报告]
发表于 2016-08-19 21:33 |只看该作者

  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;

  4. use v5.14;
  5. use autodie;
  6. use Data::Dumper;

  7. use List::Util qw/sum/;

  8. sub load_data {
  9.   local @ARGV = @_;

  10.   my %records;

  11.   # Ignore header line
  12.   readline;

  13.   while (<>) {
  14.     my ($chr, $pos, $y) = split;
  15.     my $idx = int $pos / 100_000;

  16.     push @{$records{$chr}->[$idx]}, $y;
  17.   }

  18.   return wantarray ? %records : \%records;
  19. }

  20. ###

  21. my $records = load_data $ARGV[0];

  22. while (my ($chr, $val) = each %$records) {
  23.   while (my ($idx, $ys) = each @$val) {
  24.     my $m = defined($ys) ? (sum(@$ys) / @$ys) : 0;
  25.     say join("\t", $chr, ($idx+1)*100_000, $m);
  26.   }
  27. }
复制代码

评分

参与人数 1信誉积分 +10 收起 理由
sunzhiguolu + 10 太牛B了!!!

查看全部评分

论坛徽章:
0
6 [报告]
发表于 2016-08-21 19:34 |只看该作者
请问下下面这行代码什么意思啊,定义一个哈希?直接my $data_href = {}不就行了吗?前面加号表示什么啊?谢谢!

  1. my $data_href = +{};
复制代码

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
7 [报告]
发表于 2016-08-21 20:49 |只看该作者

论坛徽章:
0
8 [报告]
发表于 2016-08-23 14:43 |只看该作者
好的,谢谢大神~

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
9 [报告]
发表于 2016-08-23 14:48 |只看该作者
作业要自己写. 实在不会在问人.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP