请大家帮忙看看这个问题,关于矩阵计算
时间:2010-09-08
来源:互联网
求教一个算法,上次问过,但是还是没有搞清楚。
比如有这样一个矩阵:
sox 7.2 3.8 6.8 9.2 5.6
sox 5.4 2.3 4.6 8.9 9.0
sox 6.7 NA 7.8 9.0 3.1
goo 2.4 6.7 NA 9.0 2.1
goo 2.1 5.6 7.8 9.7 1.2
pkk 2.5 4.3 6.5 4.9 0.2
pkk 2.1 3.4 3.2 NA 4.6
pkk 3.2 5.6 6.7 9.1 2.2
...
...
...
这个矩阵很简单,就是有一些同名的行,现在我要做的是,把这些同名的行的数据按每一列合并起来,按什么合并,按照每一列的平均值来合并
就是说,比如行名为sox的行,第一列数据为: 7.2, 5.4, 6.7 那么第一列的平均值就是(7.2+5.4+6.7)/3=6.4,
第二列数据为3.8, 2.3, NA, 那么平均值就是 (3.8+2.3)/2=3, 以此类推,得到每一列的平均值,作为最后的值,那么行名为sox的行最后就合并为:
sox 6.4 3 ....
就是要写这样一个程序,原理很简单吧,但是鄙人的水平有限,写的程序效率上不去。
我是这样写的,
先用一个hash存下所有的行名:sox, goo, pkk.....
然后遍历这个hash, foreach (%hash) { }
每一次,把相同行名的行取出来放到一个数组@num中
这个矩阵有一个值是确定的,那就是列数是确定的,所以对每一个数组@num, 我用for($i=0;$i<列数;$i++) 循环,把每一列取出来,放到一个新的数组@haha中
然后for($j=0;$j<@haha;$j++) 把@haha的平均值算出来,作为这一列的最后的值
就是这样。。。
程序我是写出来了,对于行数和列数都比较少的情况,程序没有什么问题。但是如果我有大量的行和列,比如有40000行,500列,这种情况下,这个程序就不是一两天能跑完的了。我跑了三天,还没有跑完。工作情况是不允许我跑这么久的。
恳请高手们帮忙指教。非常感谢!
比如有这样一个矩阵:
sox 7.2 3.8 6.8 9.2 5.6
sox 5.4 2.3 4.6 8.9 9.0
sox 6.7 NA 7.8 9.0 3.1
goo 2.4 6.7 NA 9.0 2.1
goo 2.1 5.6 7.8 9.7 1.2
pkk 2.5 4.3 6.5 4.9 0.2
pkk 2.1 3.4 3.2 NA 4.6
pkk 3.2 5.6 6.7 9.1 2.2
...
...
...
这个矩阵很简单,就是有一些同名的行,现在我要做的是,把这些同名的行的数据按每一列合并起来,按什么合并,按照每一列的平均值来合并
就是说,比如行名为sox的行,第一列数据为: 7.2, 5.4, 6.7 那么第一列的平均值就是(7.2+5.4+6.7)/3=6.4,
第二列数据为3.8, 2.3, NA, 那么平均值就是 (3.8+2.3)/2=3, 以此类推,得到每一列的平均值,作为最后的值,那么行名为sox的行最后就合并为:
sox 6.4 3 ....
就是要写这样一个程序,原理很简单吧,但是鄙人的水平有限,写的程序效率上不去。
我是这样写的,
先用一个hash存下所有的行名:sox, goo, pkk.....
然后遍历这个hash, foreach (%hash) { }
每一次,把相同行名的行取出来放到一个数组@num中
这个矩阵有一个值是确定的,那就是列数是确定的,所以对每一个数组@num, 我用for($i=0;$i<列数;$i++) 循环,把每一列取出来,放到一个新的数组@haha中
然后for($j=0;$j<@haha;$j++) 把@haha的平均值算出来,作为这一列的最后的值
就是这样。。。
程序我是写出来了,对于行数和列数都比较少的情况,程序没有什么问题。但是如果我有大量的行和列,比如有40000行,500列,这种情况下,这个程序就不是一两天能跑完的了。我跑了三天,还没有跑完。工作情况是不允许我跑这么久的。
恳请高手们帮忙指教。非常感谢!
作者: duziteng 发布时间: 2010-09-08
本帖最后由 iamlimeng 于 2010-09-08 06:55 编辑
按你的思路,内存开销会很大,效率也较低。实际上,可以读一行数据,马上就计算,而不是存储进数组后再处理。
我按你的数据结构随机生成了一个数据文件,40000行,每行501列(0-10之间的随机数,一位小数),共300个关键字,以制表符分隔列,数据文件大小76.2M,在我的计算机上跑,需要146秒(CPU: P4 2.4G),内存占用非常小,主要是占用CPU用于计算。
代码如下,供你参考:
复制代码
如果去掉进度显示,能快10秒左右,但有进度显示,心里更有底。
另:本程序允许不同关键字,有不同的列宽。
按你的思路,内存开销会很大,效率也较低。实际上,可以读一行数据,马上就计算,而不是存储进数组后再处理。
我按你的数据结构随机生成了一个数据文件,40000行,每行501列(0-10之间的随机数,一位小数),共300个关键字,以制表符分隔列,数据文件大小76.2M,在我的计算机上跑,需要146秒(CPU: P4 2.4G),内存占用非常小,主要是占用CPU用于计算。
代码如下,供你参考:
- #!/usr/bin/perl
-
- use strict;
- use warnings;
- use Benchmark;
- my $TT0 = new Benchmark;
-
- local $| = 1;
- my $x;
- print " Calculating...\n\n";
- my %data;
- open (FH,"<data.txt");
- while (<FH>) {
- chomp;
- my @rows = split /\t/;
- foreach my $n (1..$#rows) {
- next if (uc($rows[$n]) eq 'NA');
- $data{$rows[0]}{$n}{'total'} += $rows[$n];
- $data{$rows[0]}{$n}{'count'}++;
- }
- $x++;
- print "\r $x lines calculated OK!";
- }
- close FH;
-
- open (FH,">data_caculated.txt");
- foreach my $str (sort keys %data) {
- my $line .= $str;
- my @rows = keys %{$data{$str}};
- foreach my $n (1..$#rows+1) {
- $line .= "\t".sprintf("%.2f",$data{$str}{$n}{'total'}/$data{$str}{$n}{'count'});
- }
- print FH "$line\n";
- }
- close FH;
-
- # print benchmark result
- my $TT1 = new Benchmark;
- my $td = Benchmark::timediff($TT1, $TT0);
- $td = Benchmark::timestr($td);
- print "\n\n Time expend: $td\n\n Press Enter to close me ... \7";
-
- <STDIN>;
另:本程序允许不同关键字,有不同的列宽。
作者: iamlimeng 发布时间: 2010-09-08
用数据库会不会快点?
作者: yybmsrs 发布时间: 2010-09-08
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28