2017-02-09 16 views
0

行を反復処理するときに一部の列値を更新したいが、時間がかかりすぎる。私は、iterrows()の代わりにherehereを使用し、1回の反復で2つの列を更新したいので、apply関数を使用することはできません。Python Pandas:行の反復処理中にDataFrame値を更新する

私のケースでは、以下のコードとは無関係の10列以上の列が含まれているので、私は単純な例を使用します。ここにそれらを含めると、コードが悪化します。

import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.random.randint(0, 5, size=(90000, 4)), 
        columns=['Initial', 'A', 'B']) 

df['code'] = list('KLMNOP' * 15000) # Adding column 'code' 

df = df.sort_values('code') # Sorting the df by 'code' 

df['Total'] = np.nan 

そして、IはABの値に基づいて、カラムInitialTotalを更新したい、その後、前の行のTotalによってInitialを更新します。 Iは電流codeコード前の行のcode

def produce_total(init, a, b): 
    if a >= 2 and b >= 2: 
     return init + 1 
    return init 

last_code = '' 
last_total = -100 
for row in df.itertuples(): 
    # Print the current checkpoint 
    if(row.Index % 1000 == 0): 
     print row.Index 

    # Carry over the prev Total to current Initial 
    if last_code == row.code: 
     df.loc[row.Index, 'Initial'] = last_total 

    # Prepare the updated Initial value 
    # Because what is inside 'row' seems unaffected by the update 
    new_initial = df.loc[row.Index, 'Initial'] 

    # Find Total and assign to the df 
    new_total = produce_total(
     new_initial, 
     row.A, 
     row.B 
    ) 
    df.loc[row.Index, 'Total'] = new_total 

    last_code = row.code 
    last_total = new_total 

に等しい場合Totalが次の行のInitialに持ち越され、平均はほぼ時間走ったが、唯一のインデックス30000-ISH達します。これを行うためのもう1つまたは2つの効率的な方法のためのアイデアや提案?

または、私が考慮する必要がある他の側面があります(いくつかの列の削除など)?

ありがとうございます!

答えて

0

IIUCは、あなたがこれは私が最初の合計は、& Bの値が2より大きい場合、これまで、常に& -100であるに1を追加する必要がある各コードのために、仮定するものであるpandas cumsum

使用する必要があります前の行の合計

import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.random.randint(0, 5, size=(90000, 3)), 
        columns=['Initial', 'A', 'B']) 
df['code'] = list('KLMNOP' * 15000) # Adding column 'code' 

df = df.sort_values('code') # Sorting the df by 'code' 

df['new_Initial'] = np.where((df.A>2) & (df.B>2) ,1,0) 

df.set_value(0, 'new_Initial', -100) 
df.set_value(1, 'new_Initial', -100) 
df.set_value(2, 'new_Initial', -100) 
df.set_value(3, 'new_Initial', -100) 
df.set_value(4, 'new_Initial', -100) 

df['Total'] = df.groupby(['code']).new_Initial.cumsum() 
print df 

出力

 Initial A B code new_Initial Total 
0   1 0 2 K   -100 -100 
84312  4 1 2 K   0 -100 
34110  1 4 0 K   0 -100 
34104  2 0 4 K   0 -100 
34098  0 4 3 K   1 -99 
34092  4 1 0 K   0 -99 
34086  2 2 4 K   0 -99 
34080  1 2 2 K   0 -99 
84318  4 2 2 K   0 -99 
34074  2 3 2 K   0 -99 
34116  2 1 1 K   0 -99 
34068  4 3 0 K   0 -99 
34056  4 3 4 K   1 -98 
34050  2 4 1 K   0 -98 
34044  1 1 0 K   0 -98 
84324  1 0 2 K   0 -98 
34038  0 1 0 K   0 -98 
34032  1 2 0 K   0 -98 
34026  0 1 1 K   0 -98 
34020  0 4 4 K   1 -97 
34014  0 0 4 K   0 -97 
34062  4 0 3 K   0 -97 
34122  2 3 3 K   1 -96 
34128  1 1 1 K   0 -96 
34134  3 2 3 K   0 -96 
34242  0 1 3 K   0 -96 
34236  4 3 2 K   0 -96 
34230  4 3 1 K   0 -96 
34224  4 2 0 K   0 -96 
84294  2 3 2 K   0 -96 
     ... .. .. ...   ... ... 
51245  4 4 0 P   0 2355 
51239  3 3 1 P   0 2355 
51365  0 1 2 P   0 2355 
51371  1 3 4 P   1 2356 
51377  4 2 3 P   0 2356 
51383  0 2 2 P   0 2356 
51515  0 2 1 P   0 2356 
51509  4 2 2 P   0 2356 
51503  3 0 0 P   0 2356 
51497  1 3 0 P   0 2356 
51491  4 3 2 P   0 2356 
51485  3 3 2 P   0 2356 
51479  4 0 3 P   0 2356 
51473  2 3 3 P   1 2357 
51467  3 4 3 P   1 2358 
51461  4 0 2 P   0 2358 
51827  4 0 2 P   0 2358 
51455  1 2 1 P   0 2358 
51443  3 0 4 P   0 2358 
51437  0 0 4 P   0 2358 
51431  2 2 2 P   0 2358 
51425  3 2 1 P   0 2358 
51419  2 3 2 P   0 2358 
51413  2 0 2 P   0 2358 
51407  0 1 3 P   0 2358 
51401  4 2 2 P   0 2358 
51395  2 4 4 P   1 2359 
51389  1 3 3 P   1 2360 
51449  3 4 0 P   0 2360 
89999  0 1 4 P   0 2360 
関連する問題