2017-08-21 17 views
1

私は、100年の日付をインデックスとして(つまり〜36500列)100年の日付をインデックス(つまり〜36500行)として持つ非常に大きなデータフレームを持っています。私は36500^2回実行する必要があるデータフレームの各要素の値を計算する関数を持っています。非常に大きなデータフレームを値で高速に取り込む方法

問題は、かなり高速な機能ではなく、データフレームへの値の割り当てです。このように定数を代入しても、6つの代入ごとに約1秒かかります。もちろん、私はあなたが言うことができるようにかなり厚いです:C/Javaで通常

for i, row in df_mBase.iterrows(): 
    for idx, val in enumerate(row): 
     df_mBase.ix[i][idx] = 1 
    print(i) 

私は単に36500x36500重ループをループし、インデックスを経由して直接事前に割り当てられたメモリにアクセスほとんどで、一定時間内に達成することはできないでしょうオーバーヘッド。しかし、これはpythonのオプションではないようです?

このデータをデータフレームに格納する最も速い方法は何でしょうか? Pythonianかどうか、私はスピードの後でしかない - 私は優雅さを気にしない。

+0

僅差としてdf.iteritems()で列を反復処理して、最速の作品df[column][index] = x、ベクトル化することができない場合データ? CSV? –

+0

何が欲しいですか?すべて1のデータフレーム? –

答えて

2

ネイティブのPythonまたはnumpyでデータ構造を作成し、そのデータをDataFrameコンストラクタに渡す必要があります。関数がnumpyの関数/演算を使用して記述できる場合は、numpyのベクトル化された性質を使用して、すべてのインデックスをループさせないようにすることができます。ここで

が作っ機能を持つ例です。

import numpy as np 
import pandas as pd 
import datetime as dt 
import dateutil as du 

dates = [dt.date(2017, 1, 1) - du.relativedelta.relativedelta(days=i) for i in range(36500)] 
data = np.zeros((36500,36500), dtype=np.uint8) 

def my_func(i, j): 
    return (sum(divmod(i,j)) - sum(divmod(j,i))) % 255 

for i in range(1, 36500): 
    for j in range(1, 36500): 
     data[i,j] = my_func(i,j) 

df = pd.DataFrame(data, columns=dates, index=dates) 

df.head(5) 
#returns: 

      2017-08-21 2017-08-20 2017-08-19 2017-08-18 2017-08-17 \ 
2017-08-21   0   0   0   0   0 
2017-08-20   0   0   254   253   252 
2017-08-19   0   1   0   0   0 
2017-08-18   0   2   0   0   1 
2017-08-17   0   3   0   254   0 

       ...  1917-09-19 1917-09-18 1917-09-17 1917-09-16 
2017-08-21  ...    0   0   0   0 
2017-08-20  ...    225   224   223   222 
2017-08-19  ...    114   113   113   112 
2017-08-18  ...    77   76   77   76 
2017-08-17  ...    60   59   58   57 
+0

これは魔法として機能します。これを早急に行うための他のトリックはありますか?下位レベルコードなど?ツ! – afora377

3

これは

.IX

.ixを遅らせる可能性がある、いくつかの理由がありますが行うことができます魔法の種類インデクサ、ありますラベルベースの場合は.loc、インデックスベースの場合は.ilocとなり、となります。 私は.ixは、ラベルやロケーションベースのインデックスが

.iterrows

各行について(新しい?)Seriesを返すが必要とされているかどうかを把握するために舞台裏で、魔法の多くを行うと仮定します。 .iteritems

列上を反復するように、列ベースの反復は、[] []

df_mBase.ix[i][idx]Seriesを返し、それから要素idxをとり、値1

を割り当てられますれ、速いかもしれません
df_mBase.loc[i, idx] = 1 

この

ベンチマーク

を向上させる必要があります0
       0.03  0.1   0.3   1.0   3.0 
assign_applymap    0.001989 0.009862 0.018018 0.105569 0.549511 
assign_vectorized    0.002974 0.008428 0.035994 0.162565 3.810138 
assign_index     0.013717 0.137134 1.288852 14.190128 111.102662 
assign_column2    0.026260 0.186588 1.664345 19.204453 143.103077 
assign_column     0.016811 0.212158 1.838733 21.053627 153.827845 
assign_itertuples    0.025130 0.249886 2.125968 24.639593 185.975111 
assign_iloc_product_range  0.026982 0.247069 2.199019 23.902244 186.548500 
assign_iloc_product   0.021225 0.233454 2.437183 25.143673 218.849143 
assign_loc_product   0.018743 0.290104 2.515379 32.778794 258.244436 
assign_loc     0.029050 0.349551 2.822797 32.087433 294.052933 
assign_original    0.034315 0.337207 2.714154 30.361072 332.327008 

結論

timing plot

あなたはそう、ベクトル化を使用することができます。計算によっては、別の方法を使用することもできます。使用する値だけが必要な場合は、applymapが最速のようです。あなたは、あまりにも列

と仕事をインデックスと-または列が必要な場合は、あなたが取得しているところから、

+0

元のコードを推奨されたコードの最後の行に置き換えると、実際に何らかの理由でコードが2倍遅くなります。 – afora377

+0

私はあなたの結果が非常に興味深いと感じたので、いくつかのベンチマークを実行しました –

関連する問題