免费注册 查看新帖 |

Chinaunix

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

使用perl除去常数列 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-31 09:56 |只看该作者 |倒序浏览
现在有一个数据文件如下:
No  v1  v2  v3  v4  v5  v6  ...
1    2.3 3.5 4.1 4.5 3.5 6
2    3.2 3.4 4.1 4.2 3.5 7
3    2.6 2.2 4.1 3.3 3.5 4.4
4    1.1 2.2 4.1 3.7 3.5 5.6
...

现在我需要将常数列(一列中的数据全部相同,如上例中的v3和v5)除去,并获取剩下的数据集,请问使用perl如何实现?

论坛徽章:
0
2 [报告]
发表于 2012-08-31 12:27 |只看该作者
实现倒不难,就是太啰嗦,我想应该有更简洁的实现方法,你将就用吧
  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;
  4. my %data;
  5. my %filter;
  6. while (<DATA>) {
  7.         chomp;
  8.         my ($no,@data) = split /\s+/;
  9.          $data{$no} = \@data;
  10.          foreach my $n (0..$#data) {
  11.                  $filter{$n}{$data[$n]} = 1;
  12.          }
  13. }
  14. my %same;
  15. foreach my $rol (keys %filter) {
  16.         $same{$rol} = 1 if (keys %{$filter{$rol}} == 1);
  17. }
  18. foreach my $no (sort keys %data) {
  19.         print "$no\t";
  20.          my @data_new = ();
  21.          foreach my $rol (0..$#{$data{$no}}) {
  22.                  push(@data_new,${$data{$no}}[$rol]) if (!$same{$rol});
  23.          }
  24.          print join("\t",@data_new),"\n";
  25. }
  26. <STDIN>;

  27. __DATA__
  28. 1    2.3 3.5 4.1 4.5 3.5 6
  29. 2    3.2 3.4 4.1 4.2 3.5 7
  30. 3    2.6 2.2 4.1 3.3 3.5 4.4
  31. 4    1.1 2.2 4.1 3.7 3.5 5.6
复制代码

论坛徽章:
0
3 [报告]
发表于 2012-08-31 12:28 |只看该作者
我先抛块砖吧
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. my (@row,%col);
  5. while (<DATA>) {
  6.     my @data = split;
  7.     push @row,[@data];
  8.     $col{$_}{$data[$_]}++ for 0..$#data;
  9. }

  10. foreach my $i (0..$#row) {
  11.     foreach my $j (0..$#{$row[$i]}) {
  12.         if ( keys %{ $col{$j} } > 1) {
  13.             print $row[$i][$j],"\t";
  14.         }
  15.     }
  16.     print "\n";
  17. }

  18. __DATA__
  19. 2.3 3.5 4.1 4.5 3.5 6
  20. 3.2 3.4 4.1 4.2 3.5 7
  21. 2.6 2.2 4.1 3.3 3.5 4.4
  22. 1.1 2.2 4.1 3.7 3.5 5.6
复制代码

论坛徽章:
0
4 [报告]
发表于 2012-08-31 13:34 |只看该作者
感谢两位的回复,我以前使用java实现过,就是太麻烦,要转置两次
perl是初学

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
5 [报告]
发表于 2012-08-31 13:34 |只看该作者
  1. use strict;
  2. use warnings;
  3. use List::MoreUtils qw( uniq );

  4. my @datas;

  5. while (<DATA>) {
  6.     my ($no, @ds) = split;
  7.     push @{$datas[$_]}, $ds[$_] for (0..$#ds);
  8. }
  9. @datas = grep { scalar(uniq @{$_}) > 1; } @datas;
  10. for my $i (0..$#{$datas[0]}) {
  11.     my @tmp = ($i + 1);
  12.     push @tmp, @{$_}[$i] for (@datas);
  13.     print join("\t", @tmp), "\n";
  14. }

  15. __DATA__
  16. 1    2.3 3.5 4.1 4.5 3.5 6
  17. 2    3.2 3.4 4.1 4.2 3.5 7
  18. 3    2.6 2.2 4.1 3.3 3.5 4.4
  19. 4    1.1 2.2 4.1 3.7 3.5 5.6
复制代码

论坛徽章:
0
6 [报告]
发表于 2012-08-31 14:26 |只看该作者
感觉需要把整个文件都读了,才能做下一步,如果文件很大的话要小心了。
或者读两遍文件。
第一遍看哪列数据没变化过,
第二遍读,写。

论坛徽章:
0
7 [报告]
发表于 2012-08-31 15:19 |只看该作者
我做了些修改:
  1. use strict;
  2. use warnings;

  3. open my $fh, '<', 'C:/Users/pumbaa/Desktop/test/1.txt';
  4. open my $fh2, '>', 'C:/Users/pumbaa/Desktop/test/2.txt';

  5. my (@title, @row, %col);
  6. my $flag = 1;
  7. while (<$fh>) {
  8.         chomp;
  9.         if($flag) {
  10.                 (@title) = split /\t/;
  11.                 $flag = 0;
  12.                 next;
  13.         }       
  14.     my (@data) = split /\t/;
  15.     push @row,[@data];
  16.     $col{$_}{$data[$_]}++ for 0..$#data;
  17. }

  18. $flag = 1;
  19. foreach my $i (0..$#row) {
  20.     foreach my $j (0..$#{$row[$i]}) {
  21.         if ( keys %{ $col{$j} } > 1) {
  22.                 if ($flag) {
  23.                         print $fh2 $title[$j], "\t";
  24.                         next;
  25.                 }
  26.             print $fh2 $row[$i][$j],"\t";
  27.         }
  28.     }
  29.     print $fh2 "\n";
  30.     if($flag) {
  31.             $flag = 0;
  32.             redo;
  33.     }   
  34. }
复制代码
1.txt
no        v1        v2        v3        v4        v5        v6
1        2.2        3.4        5.6        7.8        9.9        10
2        2.2        3.6        5.6        7.8        9.9        11
3        2.2        1.2        3.5        2.1        9.9        12
4        2.2        1.1        1.3        1.4        9.9        13

2.txt
no        v2        v3        v4        v6       
1        3.4        5.6        7.8        10       
2        3.6        5.6        7.8        11       
3        1.2        3.5        2.1        12       
4        1.1        1.3        1.4        13       

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
8 [报告]
发表于 2012-08-31 22:44 |只看该作者
chembaobao 发表于 2012-08-31 15:19
我做了些修改:1.txt
no        v1        v2        v3        v4        v5        v6
1        2.2        3.4        5.6        7.8        9.9        10


结果很好
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP