免费注册 查看新帖 |

Chinaunix

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

求助:perl求关键字相同行的均值[已解决] [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-03-18 21:22 |只看该作者 |倒序浏览
本帖最后由 流星北 于 2010-03-19 12:10 编辑

用perl解决。
有一个文本数据集,在excel中通过排序后发现,行首的关键字,有的行有重复,希望求有重复关键字行的均值,在文件中没有重复关键字的行按原样输出,有重复关键字的行,只输出均值一行。
CA6        1       2      3       4      5       
CA7        2       5      3       2      1
CA8        2       8      6       3      2                       
CA8        3       4      4       1      5               
CA9        5       8       7      6      1       
希望能得到:
CA6        1       2      3       4      5       
CA7        2       5      3       2      1
CA8        2.5    6      5       2      3.5       
CA9        5       8       7      6      1

每一行除了行首的关键字,有78个值。关键字大部分是唯一的,一个关键字对应一行数据,重复关键字的,行数量不一定。
请各位高手指点,在此谢过大家!

论坛徽章:
0
2 [报告]
发表于 2010-03-18 21:43 |只看该作者
恩。。but,,,,, what's your code so far?

论坛徽章:
0
3 [报告]
发表于 2010-03-18 22:51 |只看该作者
本帖最后由 黑色阳光_cu 于 2010-03-18 22:58 编辑

  1. #!/bin/env perl

  2. use strict;
  3. use warnings;

  4. my @lines;
  5. my @stack;
  6. my $keyword;
  7. my $sp = " " x 8;

  8. foreach $_ (sort { &filter($a, $b) } <DATA>)
  9. {
  10.         my @fields = split(/\s+/, $_);
  11.         $keyword = $fields[0] if (not defined $keyword);
  12.         if ($keyword ne $fields[0])
  13.         {
  14.                 push(@lines, &average());
  15.                 @stack = (\@fields);
  16.                 $keyword = $fields[0];
  17.         }
  18.         else
  19.         {
  20.                 push(@stack, \@fields);
  21.         }
  22. }

  23. push(@lines, &average());
  24. die join("\n", @lines), "\n";

  25. sub filter
  26. {
  27.         return (split(/\s+/, $_[0]))[0] cmp (split(/\s+/, $_[1]))[0];
  28. }

  29. sub average()
  30. {
  31.         my $result;
  32.         for (my $n = 1; $n <= $#stack; $n++)
  33.         {
  34.                 for (my $nn = 1; $nn <= $#{$stack[$n]}; $nn++)
  35.                 {
  36.                         $stack[0]->[$nn] += $stack[$n]->[$nn];
  37.                 }
  38.         }

  39.         for (my $nn = 1; $nn <= $#{$stack[0]}; $nn++)
  40.         {
  41.                 $stack[0]->[$nn] /= $#stack + 1;
  42.         }

  43.         $result = join($sp, @{$stack[0]});
  44.         @stack = ();
  45.         return $result;
  46. }

  47. __DATA__
  48. CA6        1       2      3       4      5      
  49. CA7        2       5      3       2      1
  50. CA8        2       8      6       3      2                       
  51. CA8        3       4      4       1      5               
  52. CA9        5       8       7      6      1   
复制代码

论坛徽章:
0
4 [报告]
发表于 2010-03-18 23:47 |只看该作者
呵呵··看见带妹了··

论坛徽章:
0
5 [报告]
发表于 2010-03-19 09:44 |只看该作者
本帖最后由 toniz 于 2010-03-19 09:57 编辑

论坛徽章:
0
6 [报告]
发表于 2010-03-19 09:58 |只看该作者
本帖最后由 黑色阳光_cu 于 2010-03-19 09:59 编辑
toniz 发表于 2010-03-19 09:44
  1. use strict;
  2. use Data::Dumper;

  3. my %data;
  4. while(<DATA>){
  5.     s/\s+$//g;
  6.     s/ +/\t/g;
  7.     my @dtmp = split /\t/,$_;
  8.     my $key = shift @dtmp;
  9.     if (exists $data{$key}){            
  10.         $data{$key}=[map{($dtmp[$_]+${$data{$key}}[$_])/2}0..(@dtmp-1)];
  11.     }else{
  12.         $data{$key}=\@dtmp;
  13.     }   
  14. }

  15. foreach my $key(sort keys %data){
  16.     print $key," "x8,join " "x8,@{$data{$key}},"\n";
  17. }


  18. __DATA__
  19. CA6        1       2      3       4      5        
  20. CA7        2       5      3       2      1
  21. CA8        2       8      6       3      2                        
  22. CA8        3       4      4       1      5               
  23. CA9        5       8       7      6      1
复制代码

论坛徽章:
0
7 [报告]
发表于 2010-03-19 10:09 |只看该作者
黑色阳光_cu 发表于 2010-03-18 22:51



    谢谢大哥的回复,程序在示例数据上面运行得很好。但是文本数据太大,我希望通过文件操作来处理,我自己加入了文件打开,文件读取,文件写入命令,出来的结果文件不对。附件里面是我的部分数据。请看看这个怎么解决。

论坛徽章:
0
8 [报告]
发表于 2010-03-19 10:11 |只看该作者
把 foreach $_ (sort { &filter($a, $b) } <DATA>)
改为 while ($_ = <FILE>)

前提是文件是排序过的

试试

论坛徽章:
0
9 [报告]
发表于 2010-03-19 10:16 |只看该作者
本帖最后由 toniz 于 2010-03-19 11:15 编辑

那个有BUG  我编辑了 呵呵
  1. use strict;
  2. use Data::Dumper;

  3. my %data;
  4. while(<DATA>){
  5.                 s/\s+$//g;
  6.                 s/ +/\t/g;
  7.                 my @dtmp = split /\t/,$_;
  8.                 my $key = shift @dtmp;
  9.                 if (exists $data{$key}){                       
  10.                                 $data{$key}->{'data'}=[map {$dtmp[$_]+${$data{$key}->{'data'}}[$_]}0..(@dtmp-1)];
  11.                                 $data{$key}->{'count'}+=1;
  12.                 }else{
  13.                                 $data{$key}->{'data'}=\@dtmp;
  14.                                 $data{$key}->{'count'} =1;
  15.                 }               
  16. }

  17. foreach my $key(sort keys %data){
  18.                 my @tmp = map {$_/$data{$key}->{'count'}}@{$data{$key}->{'data'}};
  19.                 print $key," "x8,join " "x8,@tmp ,"\n";
  20. }


  21. __DATA__
  22. CA6        1       2      3       4      5        
  23. CA7        2       5      3       2      1
  24. CA8        2       8      6       3      2                        
  25. CA8        3       4      4       1      5               
  26. CA9        5       8       7      6      1
复制代码

论坛徽章:
0
10 [报告]
发表于 2010-03-19 10:19 |只看该作者


你的代码比我少多了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP