2016-06-16 13 views
1

私は、タブ区切りのテキストファイルから読み込み、ワイドフォーマットからロングフォーマットに変換して新しいテキストファイルに書き出すために、約5400万行のデータセットを持っています。データが大きすぎてメモリに収まらないので、イテレータを使用しています。そこで私は長い間に広いから移動したい3つの別々の変数があるので、私はそれらの3つの別々のイテレータすべてusecolsリストが共通の識別子とそうでない場合は個別の列が含まれている時間効率の良いワイドからロングへの変換パンダ

import pandas as pd 
import itertools as it 

filename = "C:/example.txt" 
iter_a = pd.read_table(filename, iterator=True, usecols=col_list_1, chunksize=100000) 
iter_b = pd.read_table(filename, iterator=True, usecols=col_list_2, chunksize=100000) 
iter_c = pd.read_table(filename, iterator=True, usecols=col_list_3, chunksize=100000) 

を使用してきました。列名は年と属性に基づいているので、列リストが次のようになります。

col_list_1 = ['Key', 'A90', 'A91', 'A92'] 
col_list_2 = ['Key', 'B90', 'B91', 'B92'] 
col_list_3 = ['Key', 'C90', 'C91', 'C92'] 

そして、私はすべての列名を変更する主要な文字/文字なしのちょうど年に、そして年に溶融したいだけ。

new_colnames = ['Key', '1990', '1991', '1992'] 
melt_values = ['1990', '1991', '1992'] 

for achunk, bchunk, cchunk in it.izip(iter_a, iter_b, iter_c): 
    achunk.columns = new_colnames 
    bchunk.columns = new_colnames 
    cchunk.columns = new_colnames 

    melted_a = pd.melt(achunk, id_vars='Key', value_vars=melt_values, var_name='Year', value_name='A').set_index(['Key', 'Year']).sort_index() 
    melted_b = pd.melt(bchunk, id_vars='Key', value_vars=melt_values, var_name='Year', value_name='B').set_index(['Key', 'Year']).sort_index() 
    melted_c = pd.melt(cchunk, id_vars='Key', value_vars=melt_values, var_name='Year', value_name='C').set_index(['Key', 'Year']).sort_index() 

    join1 = melted_a.join(melted_b, how='outer') 
    join2 = join1.join(melted_c, how='outer') 
    join2.dropna(inplace=True, how='all') 

    join2.to_csv('C:/output_example.txt', sep='\t') 

これは機能しますが、非常に時間がかかります。私は15秒で100,000行のチャンクで1回の繰り返しを計時しました。線形にスケーリングすると仮定すると、私は2.25時間のランタイムを見ているようです。私はこれをスピードアップできる良い方法はありますか?たぶんnumpy配列やマルチプロセッシングを使用していますか?

+0

入力ファイルはすべて同じキーを持ち、同じ順序であると仮定できますか? (チャンクされた結合はそれ以外の点では意味がありません)また、 'value_name = 'A''が3回あります。これはタイプミスですか?そして、データ数値ですか?欠損データはどのように表されますか? –

+0

@morningsunすべての入力ファイルは同じキーと同じ順序を持っています。 'value_name = 'A''をうまくキャッチすると、それはタイプミスです。データは必ずしもすべて数値であるとは限りません。列の型は常に同じですが、異なる列は数値または文字列です。 – jesseWUT

+0

ああ、私はあなたが同じファイル*に3つのイテレータ*を持っていることを知っています。 –

答えて

2

pandas csvパーサーは本当に速いですが、pandasはあなたが本当に気にしないことをたくさんしているからです(タイプ推論&変換、すべての結合アライメント、インデックス作成など) 。

これはほんの始まりですが、これは非常に簡単な例です。あなたはそれをテストしなければなりませんが、私はそれがあなたが上でやっているより速いかもしれないと思います。

In [30]: %%file tmp.csv 
    ...: Key,A90,A91,A92,B90,B91,B92 
    ...: a,1,2,3,4,5,6 
    ...: b,7,8,9,10,11,12 

In [32]: with open('tmp.csv') as f, open('out.csv', 'w') as f2: 
    ...:  f2.write('Key,Group,Year,Value\n') 
    ...:  for i, line in enumerate(f): 
    ...:   if i == 0: 
    ...:    _, *headers = line.strip().split(',') 
    ...:    headers = [(h[0], '19' + h[1:]) for h in headers] 
    ...:   else: 
    ...:    key, *rest = line.strip().split(',') 
    ...:    for (group, year), value in zip(headers, rest): 
    ...:     f2.write(','.join([key, group, year, value]) + '\n') 

In [33]: print(open('out.csv').read()) 
Key,Group,Year,Value 
a,A,1990,1 
a,A,1991,2 
a,A,1992,3 
a,B,1990,4 
a,B,1991,5 
a,B,1992,6 
b,A,1990,7 
b,A,1991,8 
b,A,1992,9 
b,B,1990,10 
b,B,1991,11 
b,B,1992,12 
+0

私はPython 2.7を使用していることを忘れていました。*ヘッダーを解凍する簡単な回避策はありますか? – jesseWUT

+0

確かに: 'l = line.strip()。split( '、'); – chrisb

+0

純粋なpythonのアプローチの考え方は間違いありませんが、今私が探していた出力形式についてはっきりしていないことが分かりました。これは何か@rootと同じように、各ユニークなグループは行ではなく列に取り込まれます – jesseWUT

関連する問題