[완료]펄을 이용하여 세로줄 평균 값을 구하려 합니다.

ascendo의 이미지

안녕하세요 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();
 
}

이런식으로 했더니 안나오네요 하하하

사실 한줄씩만 읽어서 그런줄 알겠지만

세로줄을 어레이에 넣어서 계산하는 법을 몰라서요

혹시 아시는 분있으시면 부탁 드리겠습니다.

감사합니다.

monovision의 이미지

먼저, 전 펄은 할 줄 모릅니다.

가로줄 데이터의 갯수가 동일하다고 가정을 하면 세로줄의 데이터를 입력할 배열(가로줄 데이터 갯수 만큼이겠죠 ?) 을 생성해 두고 한 줄씩 읽으면서 차례대로 세로줄 배열에 더해가는 방법은 어떨까요 ?

너무 어렵게 고민하는게 아니신지...

aero의 이미지

일단 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";
}

결과

cluster1 1 2 3.5 2.75 3 1.5
cluster2 3 2 1 1 4 1
cluster3 1.66666666666667 2 2.33333333333333 3 1 3.66666666666667

추가로 님의 코드에 대해 몇 가지 주제넘게 참견하자면

일단 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

potatoid의 이미지

개인적으로 위 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.

aero의 이미지

#!/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";
}
ascendo의 이미지

많은 도움이 되었습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.