私はperlで多くのデータ分析を行っており、pandas、numpy、matplotlibなどを使用してPythonでこの作業を複製しようとしています.
一般的なワークフローは次のようになります。
1)ディレクトリ内のすべてのファイルをグロブします
2)メタデータがあるため、ファイルを解析します
3)正規表現を使用して、特定のファイル内の関連する行を分離します(通常、「LOOPS」などのタグで始まります)
4) タグに一致する行を分割し、データをハッシュにロードします
5) データ分析を行う
6) プロットを作成する
これは、私が通常 perl で行うことのサンプルです。
print"Reading File:\n"; # gets data
foreach my $vol ($SmallV, $LargeV) {
my $base_name = "${NF}flav_${vol}/BlockedWflow_low_${vol}_[0-9].[0-9]_-0.25_$Mass{$vol}.";
my @files = <$base_name*>; # globs for file names
foreach my $f (@files) { # loops through matching files
print"... $f\n";
my @split = split(/_/, $f);
my $beta = $split[4];
if (!grep{$_ eq $beta} @{$Beta{$vol}}) { # constructs Beta hash
push(@{$Beta{$vol}}, $split[4]);
}
open(IN, "<", "$f") or die "cannot open < $f: $!"; # reads in the file
chomp(my @in = <IN>);
close IN;
my @lines = grep{$_=~/^LOOPS/} @in; # greps for lines with the header LOOPS
foreach my $l (@lines) { # loops through matched lines
my @split = split(/\s+/, $l); # splits matched lines
push(@{$val{$vol}{$beta}{$split[1]}{$split[2]}{$split[4]}}, $split[6]);# reads data into hash
if (!grep{$_ eq $split[1]} @smearingt) {# fills the smearing time array
push(@smearingt, $split[1]);
}
if (!grep{$_ eq $split[4]} @{$block{$vol}}) {# fills the number of blockings
push(@{$block{$vol}}, $split[4]);
}
}
}
foreach my $beta (@{$Beta{$vol}}) {
foreach my $loop (0,1,2,3,4) { # loops over observables
foreach my $b (@{$block{$vol}}) { # beta values
foreach my $t (@smearingt) { # and smearing times
$avg{$vol}{$beta}{$t}{$loop}{$b} = stat_mod::avg(@{$val{$vol}{$beta}{$t}{$loop}{$b}}); # to find statistics
$err{$vol}{$beta}{$t}{$loop}{$b} = stat_mod::stdev(@{$val{$vol}{$beta}{$t}{$loop}{$b}});
}
}
}
}
}
print"File Read in Complete!\n";
私の希望は、このデータを階層インデックス付きデータ構造にロードし、perl ハッシュのインデックスが私の python データ構造のインデックスになることです。これまでに遭遇した pandas データ構造のすべての例は、構造全体 (インデックスと値) が 1 つのコマンドで手動で割り当てられ、データ構造のすべての機能を示すために操作された高度に工夫されたものです。残念ながら、分析しようとしているデータの質量、ベータ、サイズなどがわからないため、データを一度に割り当てることはできません。私はこれを間違った方法でやっていますか?これを行うより良い方法を知っている人はいますか?データファイルは不変です。正規表現を使用して解析する必要がありますが、その方法は理解しています。助けが必要なのは、平均を取ることができるようにデータを適切なデータ構造に入れることです。
典型的なデータには、長さが不明な行数のヘッダーがありますが、私が気にするのは次のようなものです。
Alpha 0.5 0.5 0.4
Alpha 0.5 0.5 0.4
LOOPS 0 0 0 2 0.5 1.7800178
LOOPS 0 1 0 2 0.5 0.84488326
LOOPS 0 2 0 2 0.5 0.98365135
LOOPS 0 3 0 2 0.5 1.1638834
LOOPS 0 4 0 2 0.5 1.0438407
LOOPS 0 5 0 2 0.5 0.19081102
POLYA NHYP 0 2 0.5 -0.0200002 0.119196 -0.0788721 -0.170488
BLOCKING COMPLETED
Blocking time 1.474 seconds
WFLOW 0.01 1.57689 2.30146 0.000230146 0.000230146 0.00170773 -0.0336667
WFLOW 0.02 1.66552 2.28275 0.000913101 0.00136591 0.00640552 -0.0271222
WFLOW 0.03 1.75 2.25841 0.00203257 0.00335839 0.0135 -0.0205722
WFLOW 0.04 1.83017 2.22891 0.00356625 0.00613473 0.0224607 -0.0141664
WFLOW 0.05 1.90594 2.19478 0.00548695 0.00960351 0.0328218 -0.00803792
WFLOW 0.06 1.9773 2.15659 0.00776372 0.0136606 0.0441807 -0.00229793
WFLOW 0.07 2.0443 2.1149 0.010363 0.018195 0.0561953 0.00296648
私が(考えて)欲しいものは、私はpythonを初めて使用し、専門家はより良いデータ構造を知っているかもしれないので、これの前に考えると、次のような階層インデックス付きシリーズです:
volume mass beta observable t value
1224 0.0 5.6 0 0 1.234
1 1.490
2 1.222
1 0 1.234
1 1.234
2448 0.0 5.7 0 1 1.234
などなど: http://pandas.pydata.org/pandas-docs/dev/indexing.html#indexing-hierarchical
perl を理解していない人のために:
私が必要としている肉とじゃがいもはこれです:
push(@{$val{$vol}{$beta}{$split[1]}{$split[2]}{$split[4]}}, $split[6]);# reads data into hash
ここにあるのは、「val」というハッシュです。これは配列のハッシュです。私はPythonが話すと信じていますが、これはリストの辞書になるでしょう。'{$something}' はハッシュ 'val' のキーであり、変数 $split[6] に格納されている値を、指定されたハッシュ要素である配列の末尾に追加しています。すべての 5 つのキーによって。これは私のデータの根本的な問題であり、関心のある各数量に対して多くのキーがあるということです。
==========
アップデート
このエラーが発生する次のコードを思いつきました。
Traceback (most recent call last):
File "wflow_2lattice_matching.py", line 39, in <module>
index = MultiIndex.from_tuples(zipped, names=['volume', 'beta', 'montecarlo_time, smearing_time'])
NameError: name 'MultiIndex' is not defined
コード:
#!/usr/bin/python
from pandas import Series, DataFrame
import pandas as pd
import glob
import re
import numpy
flavor = 4
mass = 0.0
vol = []
b = []
m_t = []
w_t = []
val = []
#tup_vol = (1224, 1632, 2448)
tup_vol = 1224, 1632
for v in tup_vol:
filelist = glob.glob(str(flavor)+'flav_'+str(v)+'/BlockedWflow_low_'+str(v)+'_*_0.0.*')
for filename in filelist:
print 'Reading filename: '+filename
f = open(filename, 'r')
junk, start, vv, beta, junk, mass, mont_t = re.split('_', filename)
ftext = f.readlines()
for line in ftext:
if re.match('^WFLOW.*', line):
line=line.strip()
junk, smear_t, junk, junk, wilson_flow, junk, junk, junk = re.split('\s+', line)
vol.append(v)
b.append(beta)
m_t.append(mont_t)
w_t.append(smear_t)
val.append(wilson_flow)
zipped = zip(vol, beta, m_t, w_t)
index = MultiIndex.from_tuples(zipped, names=['volume', 'beta', 'montecarlo_time, smearing_time'])
data = Series(val, index=index)