2017-03-24 19 views
0

私は、インデックス化されたpandasデータフレームに変換したい不明な数のデータ行を返すジェネレータを用意しています。私が知っている最速の方法は、ディスクにCSVを書き込んだり、「read_csv」で解析して戻すことです。私は空のデータフレームを作成し、常に新しい行を追加するのは効率的ではないことを認識しています。私は、返される行の数がわからないので、あらかじめ用意されたデータフレームを作成することはできません。ディスクに書き込むことなくイテレータ出力をpandasデータフレームに変換する方法はありますか?pythonイテレータの出力をpandasデータフレームに変換する最も速い方法

+1

ディスクに書き込まないでください。代わりにそれをタプルのリストにプルし、そのリストを 'pd.DataFrame'に渡します。 – James

答えて

1

このような一般的な方法がありますか?

def make_equal_length_cols(df, new_iter, col_name): 
    # convert the generator to a list so we can append 
    new_iter = list(new_iter) 
    # if the passed generator (as a list) has fewer elements that the dataframe, we ought to add NaN elements until their lengths are equal 
    if len(new_iter) < df.shape[0]: 
     new_iter += [np.nan]*(df.shape[0]-len(new_iter)) 
    else: 
     # otherwise, each column gets n new NaN rows, where n is the difference between the number of elements in new_iter and the length of the dataframe 
     new_rows = [{c: np.nan for c in df.columns} for _ in range((len(new_iter)-df.shape[0]))] 
     new_rows_df = pd.DataFrame(new_rows) 
     df = df.append(new_rows_df).reset_index(drop=True) 
    df[col_name] = new_iter 
    return df 

テストそれを:

make_equal_length_cols(df, (x for x in range(20)), 'new') 
Out[22]: 
     A B new 
0 0.0 0.0 0 
1 1.0 1.0 1 
2 2.0 2.0 2 
3 3.0 3.0 3 
4 4.0 4.0 4 
5 5.0 5.0 5 
6 6.0 6.0 6 
7 7.0 7.0 7 
8 8.0 8.0 8 
9 9.0 9.0 9 
10 NaN NaN 10 
11 NaN NaN 11 
12 NaN NaN 12 
13 NaN NaN 13 
14 NaN NaN 14 
15 NaN NaN 15 
16 NaN NaN 16 
17 NaN NaN 17 
18 NaN NaN 18 
19 NaN NaN 19 

そして渡された発電機は、データフレームよりも短い場合、それはまた、動作します:

make_equal_length_cols(df, (x for x in range(5)), 'new') 
Out[26]: 
    A B new 
0 0 0 0.0 
1 1 1 1.0 
2 2 2 2.0 
3 3 3 3.0 
4 4 4 4.0 
5 5 5 NaN 
6 6 6 NaN 
7 7 7 NaN 
8 8 8 NaN 
9 9 9 NaN 

編集:削除行単位pandas.DataFrame.appendコール、別のデータフレームを構築してワンショットで追加しました。タイミング:

新追記:

%timeit make_equal_length_cols(df, (x for x in range(10000)), 'new') 
10 loops, best of 3: 40.1 ms per loop 

旧追記:

very slow... 
1

を反復パンダのデータフレームに追加するには、最善の解決策ではありません。データをリストとして構築し、それをpd.DataFrameに渡す方が良いでしょう。

import random 
import pandas as pd 

alpha = list('abcdefghijklmnopqrstuvwxyz') 

ここでは、その後、データフレームのコンストラクタに渡し、リストを構築するためにそれを使用し、発電機を作成します。

%%timeit 
gen = ((random.choice(alpha), random.randint(0,100)) for x in range(10000)) 
my_data = [x for x in gen] 
df = pd.DataFrame(my_data, columns=['letter','value']) 

# result: 1 loop, best of 3: 373 ms per loop 

これは、発電機を作成するよりもかなり高速である、空のデータフレームを構築行を追加すると次のようになります。

%%timeit 
gen = ((random.choice(alpha), random.randint(0,100)) for x in range(10000)) 
df = pd.DataFrame(columns=['letter','value']) 
for tup in gen: 
    df.loc[df.shape[0],:] = tup 

# result: 1 loop, best of 3: 13.6 s per loop 

これは、10000行を作成するのに13秒で非常に遅いです。

関連する問題