はちゅにっき

こっちのブログはまったり更新

Text::CSV::Simple を使う

CSVファイルから、特定の列(縦方向)を切り抜きたい!
けど、どうしよぅ。そんなときはとりあえずCPAN。すると

なるモジュールを発見。さすがCPAN
METHODS のところをみてみると
want_fields という method を用いれば指定した列を抜き出せるとのこと。

そんなワケで完成したのはこんな感じ。(4列目を引っこ抜く)

#!/usr/bin/perl -w
$| = 1;

use Text::CSV::Simple;
use Inline C => 'DATA';
use warnings;
use strict;

# ファイル名指定
our $FILE_NAME = 'hoge.csv';

# CSV parse 準備
my $csv_parser = Text::CSV::Simple->new;
$csv_parser->want_fields(3);     # 4列目(0,1,2,,,と数える)を引っこ抜く (配列可)
$csv_parser->field_map('value'); # 引っこ抜く値を value と命名 (配列可)

# CSV parse
my @data = $csv_parser->read_file($FILE_NAME);

# ただの配列に変換
for (my $i = 0 ; $i < scalar @data ; $i++) { $data[$i] = $data[$i]->{value} }

# Inline::C 様にお任せ
my $average  = get_average(@data);
my $variance = get_variance($average, @data);

# 結果表示(平均値と標本分散)
print "average:  $average\n";
print "variance: $variance\n";

## -- EndOfPerl --
__DATA__


# Inline::C 様の出番
__C__
double get_average (int value, ...)
{
    Inline_Stack_Vars;
    int cnt, sigma=0;

    for (cnt = 0 ; cnt < Inline_Stack_Items ; cnt++) {
        sigma += SvIV(Inline_Stack_Item(cnt));
    }

    return (double)(sigma / cnt);
}

double get_variance (double avg, ...)
{
        Inline_Stack_Vars;
        int cnt, sigma=0;

    for (cnt = 0 ; cnt < Inline_Stack_Items ; cnt++) {
        sigma += pow(avg - (double)SvIV(Inline_Stack_Item(cnt)), 2);
    }

        return (double)(sigma / cnt);
}
__END__

read_file によって得られる配列は
ハッシュへのリファレンスとなっているようだったので
Inline::C に持ってくには、メンドクサイ。
そーんなワケで for 文を使って馬鹿みたいにただの配列へ変換してますが
もっと賢いやり方がありそうだよね。。。
map でも使えばいいのかな?

map { $_ = $_->{value} } @data;
でできた。

そもそも Inline::C を使うホドの処理じゃない気もしますg

*1:http://search.cpan.org/~tmtm/Text-CSV-Simple-1.00/lib/Text/CSV/Simple.pm