2014年8月1日金曜日

pythonで-infとか入っているデータを読み込んでnanに置き換え、その後nanに平均を代入する方法

pythonで文字と数字が混ざっていたり、空白があるデータ
#value1 value2 value3
1 2 3
4    5
6 -inf error
とかをpythonというかnumpyで読ませるにはgenfromtxtを使う。
空白や文字は自動的にnanになる。たぶん上の場合だと4 5 nanになるはず。「,」区切りで4,,5なら4 nan 5になる。

nanなら後はnumpyにあるnanmeanとかnanstdやscipyのscipy.stats.nanmedianとか使えば平均、標準偏差、中央値が出せるんだけど、-inf入ってるとこれは文字じゃなくてマイナス無限大として認識されるからやっかいって話。

genfromtxt自体は
data = numpy.genfromtxt('data.txt', comments="#", dtype="d")
みたいな感じ。dはdouble型のとき。dtypeは"f8"とかでfloat, "S5"でstring 10文字みたいにいじれる。さらにdtype=[('x','f8'), ('y','f8'), ('z', 'f8')]みたいにするとラベルつけられる。
http://retrofocus28.blogspot.com/2014/03/numpy.html
参照。
あとヘッダーがある場合はskip_header=5とかすると5行分飛ばす。

文字とか欠けているところがなかったらloadtxtでやったほうが楽かもしれん。
http://kaiseki-web.lhd.nifs.ac.jp/documents/Python/textfile.htm
http://pacocat.blogspot.com/2011/12/numpyloadtxt.html
参照。

で、置き換えするためにnumpy.whereで-infが入っているarrayを探す。
index = numpy.where(data, == float('-inf') )
で-infがある場所をindexする。たぶん上のdataの例なら
index=(array([2]), array([1]) )
か。

このindexを使ってfor文で-infをnanに置き換えしていく。
for i in range(len(index[0]))
  data[index[0][i]][index[1][i]] = float('nan')
という感じ。
index[0]がdata[0]に対応してindex[0][i]でindex[0]のarrayから1つずつ要素を取り出してくる。index[1]とdata[1]の関係も同様。で、=で代入。こんな感じでたぶん他で代入するときにもできるはず。

で、平均を測る。ここで測る平均は列の平均を測りたい。
average = numpy.nanmean(data, axis=0)
axisをつけないと全部の要素の平均、axis=0で列、axis=1で行の平均。というかpythonのarrayでの行と列、どっちがどっちだかいまだによくわかってねえ。
http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.nanmean.html
を見ること。

でnanに置き換えしたようにfor文使って平均に置き換えしていく。
for i in range(len(index[0]))
  data[index[0][i]][index[1][i]] = average[index[1][i]]
列の平均なのでindex[1]なのがミソ。

これでnumpy.savetxtで書きだす。
numpy.savetxt("test.txt", data)
たぶんこれもヘッダーつけたりとかオプションある。
http://docs.scipy.org/doc/numpy/reference/generated/numpy.savetxt.html
http://airtoxin.wordpress.com/2013/02/02/numpy-savetxt%E3%81%A7csv%E5%87%BA%E5%8A%9B%E3%82%92%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/
http://conta.hatenablog.com/entry/2013/12/02/183538
とか参照。

-infが入っててすげー疲れた。python雑魚が成長できたと思いました。

0 件のコメント:

コメントを投稿