忘记密码   免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
查看: 4877 | 回复: 7

文件每列数据统计 [复制链接]

论坛徽章:
0
发表于 2018-02-16 16:24 |显示全部楼层
本帖最后由 newfinder 于 2018-02-16 16:25 编辑

大家过年好呀!

请教大家一个问题。以文件每列为单位,对每行内容进行重复统计(包括频数和频率),如下所示。

data1.txt
---------
A B C D E F
A C D E F A
B D C E F A
E F D C G A

想输出的结果为:
data2.txt
---------
A:2, 0.50        B:1, 0.25        C:2, 0.50        C:1, 0.25        E:1, 0.25        A:3, 0.75
B:1, 0.25        C:1, 0.25        D:2, 0.50        D:1, 0.25        F:2, 0.50        F:1, 0.25
E:1, 0.25        D:1, 0.25                              E:2, 0.50        G:1, 0.25
                      F:1, 0.25

请问大家不知道有没有什么好的方法可以借鉴一下。

论坛徽章:
130
技术图书徽章
日期: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
发表于 2018-02-17 16:29 |显示全部楼层
回复 1# newfinder

  1. $ cat data1.txt
  2. A B C D E F
  3. A C D E F A
  4. B D C E F A
  5. E F D C G A

  6. $ perl get_col.pl data1.txt > data2.txt

  7. $ cat data2.txt
  8. A:2, 0.50    B:1, 0.25    C:2, 0.50    C:1, 0.25    E:1, 0.25    A:3, 0.75   
  9. B:1, 0.25    C:1, 0.25    D:2, 0.50    D:1, 0.25    F:2, 0.50    F:1, 0.25   
  10. E:1, 0.25    D:1, 0.25                 E:2, 0.50    G:1, 0.25                 
  11.              F:1, 0.25   
复制代码

                                                   

$ cat get_col.pl
  1. use strict;
  2. use warnings;

  3. sub mesg{
  4.   print "Usage:   $0 FILE\n";
  5.   print "Example: $0 data1.txt\n";
  6.   exit(1);
  7. }


  8. mesg if @ARGV !=1;

  9. my @aCol;
  10. while(<>){
  11.   s/^\s+|\s+$//g;
  12.   next if (m/^(#|$)/);
  13.   my @aData = split;
  14.   foreach( 0 .. scalar @aData-1) {
  15.     $aCol[$_]{'count'}{$aData[$_]}++;
  16.     $aCol[$_]{'total'}++;
  17.   }
  18. }
  19. my @aResult;
  20. my $sCol     = 0;
  21. my $sMax_cnt = 0;
  22. my $sMax_len = 0;
  23. foreach (@aCol) {
  24.   my $sTotal = $_->{'total'};
  25.   my $sCnt = 0;
  26.   foreach my $sKey (sort keys %{$_->{'count'}}) {
  27.     my $sVal = $_->{'count'}{$sKey};
  28.     my $sStr = sprintf("%s:%d, %.2f", $sKey, $sVal, $sVal/$sTotal);
  29.     my $sLen = length($sStr);
  30.     push @{$aResult[$sCol]},$sStr;
  31.     $sMax_cnt = $sCnt if($sMax_cnt < $sCnt);
  32.     $sMax_len = $sLen if($sMax_len < $sLen);
  33.     ++$sCnt;
  34.   }
  35.   ++$sCol;
  36. }
  37. foreach my $sCnt ( 0 .. $sMax_cnt) {
  38.   my $sLine = "";
  39.   foreach (0 .. $sCol-1) {
  40.     my $sStr = $aResult[$_]->[$sCnt] // "";
  41.     $sLine .= sprintf("%*s    ", $sMax_len, $sStr);
  42.   }  
  43.   print "$sLine\n";
  44. }
复制代码



论坛徽章:
0
发表于 2018-02-17 17:33 |显示全部楼层
回复 2# jason680

厉害厉害,多谢多谢!让我消化消化,学习学习!

论坛徽章:
0
发表于 2018-02-17 20:29 |显示全部楼层
perl count.pl data.txt > data.xls
  1. #!/usr/bin/perl

  2. use 5.010;

  3. my @data;
  4. while (<>) {
  5.     my @line = split;
  6.     for my $i ( 0 .. $#line ) {
  7.         $data[$i]{ $line[$i] }++;
  8.     }
  9. }

  10. my ($elems) = sort { $b <=> $a } map { scalar %$_ } @data;
  11. my @print = map {
  12.     my $elem = $_;
  13.     [ map { "$_: $elem->{$_}, " . ( $elem->{$_} / $. ) } keys %$elem ]
  14. } @data;

  15. for my $i ( 0 .. $elems ) {
  16.     say join "\t", map { $_->[$i] // '' } @print;
  17. }
复制代码

论坛徽章:
0
发表于 2018-02-18 18:36 |显示全部楼层
回复 4# Okelani

简洁!多谢分享了!

论坛徽章:
0
发表于 2018-03-12 18:33 |显示全部楼层
本帖最后由 L_WC 于 2018-03-12 18:37 编辑

回复 1# newfinder

重复提交了,忽略此贴。


复制代码


论坛徽章:
0
发表于 2018-03-12 18:33 |显示全部楼层
本帖最后由 L_WC 于 2018-03-12 18:43 编辑

回复 1# newfinder

今天看了Perl 6 Introduction,写的第一个Perl6程序,难免有使用不巧的地方,不足请指正。
  1. my @array_expected;
  2. my $i = 0;
  3. for 'data1.txt'.IO.lines -> $line
  4. {
  5.         next unless $line.chars;
  6.         my @line = $line.split(' ');
  7.         map ->$n {@array_expected[$n;$i] = @line[$n]} , 0 .. @line.end;
  8.         $i++;
  9. }

  10. for @array_expected -> $line
  11. {
  12.         for parse-count $line -> (:$key, :$value)
  13.         {
  14.                 say $key ~ ': ' ~ $value<count> ~ ',' ~ $value<fre>;
  15.         }
  16. }

  17. sub parse-count(@list)
  18. {
  19.         my %hash = ();
  20.         map {%hash{$_}<fre> += 1 / @list.elems; %hash{$_}<count> += 1}, @list.sort;
  21.         return %hash.sort;
  22. }
复制代码
  1. [root@Liuweic lab]# perl6 data1.pl6
  2. A: 2,0.5
  3. B: 1,0.25
  4. E: 1,0.25
  5. B: 1,0.25
  6. C: 1,0.25
  7. D: 1,0.25
  8. F: 1,0.25
  9. C: 2,0.5
  10. D: 2,0.5
  11. C: 1,0.25
  12. D: 1,0.25
  13. E: 2,0.5
  14. E: 1,0.25
  15. F: 2,0.5
  16. G: 1,0.25
  17. A: 3,0.75
  18. F: 1,0.25
复制代码




论坛徽章:
0
发表于 2018-04-05 05:55 |显示全部楼层
回复 7# L_WC

多谢多谢。我要学的还太多呀。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:wangnan@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP