[완료]펄을 이용하여 세로줄 평균 값을 구하려 합니다.
글쓴이: ascendo / 작성시간: 목, 2008/03/20 - 3:40오후
안녕하세요 ascendo 입니다.
펄을 이용하여 세로줄 평균 값을 구하려 합니다.
ID_REF 1 2 3 4 5 6
cluster1 1 2 5 1 3 1
cluster1 1 2 7 1 7 1
cluster1 1 2 1 4 1 3
cluster1 1 2 1 5 1 1
cluster2 5 2 1 1 1 1
cluster2 1 2 1 1 7 1
cluster3 1 2 5 1 1 5
cluster3 1 2 1 5 1 1
cluster3 3 2 1 3 1 5
이런 데이가 있을때
원하는 결과 값은
cluster1 x x x x x x
cluster2 x x x x x x
cluster3 x x x x x x
이렇게 나오기를 바랍니다.
Statistics::Decsriptive;
를 이용하려합니다.
#!/usr/bin/perl
use Statistics::Descriptive;
open IN,"$ARGV[0]";
$stat = Statistics::Descriptive::Full->new();
while(<IN>)
{
next if($_=~/^ID/);
chomp($_);
@line=split(' ',$_);
$want_cluster{$line[1]}=1;
if($want_cluster{$line[1]})
{
@array1=@line[2];
$mean=group_mean(@array1);
printf "%.2f\n",$mean;
}
}
sub group_mean{
my @array=@_;
$stat = Statistics::Descriptive::Full->new();
$stat->add_data(@array);
return $stat->mean();
}이런식으로 했더니 안나오네요 하하하
사실 한줄씩만 읽어서 그런줄 알겠지만
세로줄을 어레이에 넣어서 계산하는 법을 몰라서요
혹시 아시는 분있으시면 부탁 드리겠습니다.
감사합니다.
Forums:


먼저, 전 펄은 할 줄
먼저, 전 펄은 할 줄 모릅니다.
가로줄 데이터의 갯수가 동일하다고 가정을 하면 세로줄의 데이터를 입력할 배열(가로줄 데이터 갯수 만큼이겠죠 ?) 을 생성해 두고 한 줄씩 읽으면서 차례대로 세로줄 배열에 더해가는 방법은 어떨까요 ?
너무 어렵게 고민하는게 아니신지...
나름대로 만들어 봤습니다.
일단 Statistics::Descriptive 란 모듈은 이 정도 프로그램에 쓰기는 좀 크고 무거운 모듈 같습니다. 그래서 사용하지 않고 짜봤습니다.
#!/usr/bin/env perl use strict; use warnings; open my $fh, '<', $ARGV[0]; my @col = split / /, readline $fh; my %keycnt; my %keysum; while (<$fh>) { chomp $_; my @data = split / /, $_; map $keysum{$data[0]}[$_] += $data[$_], 1..$#col; ++$keycnt{$data[0]}; } foreach my $key ( sort keys %keysum ) { print $key , ' ', join( ' ', map $_/$keycnt{$key}, @{$keysum{$key}}[1..$#col] ), "\n"; }결과
추가로 님의 코드에 대해 몇 가지 주제넘게 참견하자면
일단 Perl코딩시 습관적으로 use strict; use warnings; pragma는 붙여주고 모든 변수는 명시적으로 lexical scope를 명확하게 선언하는 것이 근래 Perl의 경향이고 이로 인해 여러가지 오류와 실수의 가능성을 사전에 줄여주므로 넣기를 권합니다.
http://perl101.org/style.html
http://www.perlmonks.org/index.pl?node_id=111088
open IN,"$ARGV[0]"; 에서 요즘은 Global file handle대신 lexical filehandle을 쓰고 open도 2 argument 형식이 아니라 3 argument 형식을 쓰는게 최신 Perl의 형식입니다.
http://www.perlfoundation.org/perl5/index.cgi?outdated_techniques
구지 꼭 Statistics::Descriptive를 써야 한다면...
개인적으로 위 aero님의 펄 코드가 정말 마음에 듭니다만, 구지 꼭 Statistics::Descriptive를 써야 한다면 (대용량 데이타를 좀 더 빠르게 처리하기위해), 이렇게 하면 어정쩡하지만 그런데로 원하시는 결과를 얻을 수 있으리라 봅니다.
#!/usr/bin/env perl use strict; use Statistics::Descriptive; open IN,"$ARGV[0]"; my %want_cluster = (); my $flag = ""; my $j = 0; my @line = (); my $cluster_ref; while(<IN>) { next if($_=~/^ID/); chomp($_); @line=split(' ',$_); if ($flag ne $line[0] || $flag eq ""){ $j = 0; $flag = $line[0]; my @clusters = (); $cluster_ref = \@clusters; $want_cluster{$flag} = $cluster_ref; } for my $i (0 .. $#line){ next if $line[$i] =~ m/^cluster/; $cluster_ref->[$j][$i-1] = $line[$i]; } $j++; } sub transpose { map { my $i = $_; [ map $_->[ $i ], @_ ] } 0 .. $#{ $_[0] } }; foreach (sort keys %want_cluster){ print "$_"; my $AoA_ref = $want_cluster{$_}; my @AoA = @$AoA_ref; @AoA = transpose @AoA; my $raw = $#AoA; for my $k (0 .. $raw){ my $ref = $AoA[$k]; my $stat = Statistics::Descriptive::Full->new(); $stat->add_data(@$ref); printf " %.2f", $stat->mean(); } print "\n"; } exit 0;> Sorrow is better than laughter, because a sad face is good for the heart.
--------------------------------------------------------------------------
Sorrow is better than laughter, because a sad face is good for the heart.
제가 만든 Statistics::Descriptive 사용 버젼입니다.
#!/usr/bin/env perl use strict; use warnings; use Statistics::Descriptive; open my $fh, '<', $ARGV[0]; my @col = split / /, readline $fh; my %row; while (<$fh>) { chomp $_; my @data = split / /, $_; map { $row{$data[0]}[$_] = Statistics::Descriptive::Full->new() if not defined $row{$data[0]}[$_]; $row{$data[0]}[$_]->add_data($data[$_]); } 1..$#col; } foreach my $key ( sort keys %row ) { print $key, ' ', join( ' ', map $row{$key}[$_]->mean(), 1..$#col ), "\n"; }깔끔하긴 하지만 잦은 if연산과 add_data호출로 속도는 빠르지 않을 것 같네요.
각 배열에 대한 계산은 최종적으로 하도록 바꾼 또 다른 버젼
#!/usr/bin/env perl use strict; use warnings; use Statistics::Descriptive; open my $fh, '<', $ARGV[0]; my @col = split / /, readline $fh; my %row; while (<$fh>) { chomp $_; my @data = split / /, $_; map { push @{$row{$data[0]}[$_]}, $data[$_] } 1..$#col; } foreach my $key ( sort keys %row ) { print $key , ' ', join( ' ', map { my $tmp = Statistics::Descriptive::Full->new(); $tmp->add_data(@{$row{$key}[$_]}); $tmp->mean(); } 1..$#col ), "\n"; }답변 감사합니다.
많은 도움이 되었습니다.
댓글 달기