簡體   English   中英

Dataframe 增加了 for 循環設置列值的速度

[英]Dataframe increase speed of for loop for set value of column

我有來自熊貓的數據框(將熊貓導入為 pd)

print(df)
        C1  C2
    0    0   0
    1    0   0
    2    1   0
    3    1   1
    4    1   1
    5    0   1
    6    0   0
    7    0   0
    8    0   0
    9    1   0
    10   1   1
    11   1   1
    12   0   1
    13   0   0

我想在上升沿后在“C3”中計數 +1(上升沿從 C1 =1 和 C2=0 開始)我嘗試使用 iterrow()

count=1
df['C3'] = 0
for index, row in df.iterrows():
        if (row.C1 == 1) and (row.C2 == 0):
               count += 1 
               df.at[index, 'C3'] = count
        else:
               df.at[index, 'C3'] = count

    print(df)
         C1  C2  C3
    0    0   0   1
    1    0   0   1
    2    1   0   2
    3    1   1   2
    4    1   1   2
    5    0   1   2
    6    0   0   2
    7    0   0   2
    8    0   0   2
    9    1   0   3
    10   1   1   3
    11   1   1   3
    12   0   1   3
    13   0   0   3

對於具有 300000 行的數據幀,它有點慢,是否有一種簡單的方法可以使其更快?

非常感謝你的幫助!

你可以:

  • 創建一個系列counts ,它是您想要的條件的布爾掩碼( counts );
  • C3添加到值為1 + counts.cumsum()的原始 df

注意:pandas 根據索引值而不是 order將系列連接到數據幀。 做一些破壞 df 或counts系列的中間操作會產生意想不到的結果。

代碼:

counts = (df.C1 == 1) & (df.C2 == 0)
df["C3"] = 1 + counts.cumsum()

結果:

    C1  C2  C3
0    0   0   1
1    0   0   1
2    1   0   2
3    1   1   2
4    1   1   2
5    0   1   2
6    0   0   2
7    0   0   2
8    0   0   2
9    1   0   3
10   1   1   3
11   1   1   3
12   0   1   3
13   0   0   3

表現

讓我們比較三個選項的性能: iterrowsdf.apply和上面的矢量化解決方案:

df = pd.DataFrame(dict(C1=np.random.choice(2,size=100000), C2=np.random.choice(2,size=100000)))

df1 = df.copy(deep=True)
df2 = df.copy(deep=True)
df3 = df.copy(deep=True)

def use_iterrows():
    count=1
    df1['C3'] = 0
    for index, row in df1.iterrows():
        if (row.C1 == 1) and (row.C2 == 0):
               count += 1 
               df1.at[index, 'C3'] = count
        else:
               df1.at[index, 'C3'] = count

def use_apply():
    df2['C3'] = df2.apply(lambda x: x['C1']==1 and x['C2']==0, axis=1).cumsum()+1

def use_vectorized():
    counts = (df3.C1 == 1) & (df3.C2 == 0)
    df3["C3"] = 1 + counts.cumsum()

%timeit use_iterrows()
# 8.23 s ± 159 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)    

%timeit use_apply()
# 1.54 s ± 27.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit use_vectorized()
# 1.28 ms ± 66.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

總結:使用矢量化函數是迄今為止最快的(對於 100k 行的 df,速度快約 1000 倍(!))。 我喜歡盡可能保持使用矢量化解決方案的習慣。 df.apply的優勢在於它非常靈活,可以在難以進行矢量化操作的情況下工作。 我不認為我曾經需要 iterrows。

簡短的回答:

df['C3'] = df.apply(lambda x: x['C1']==1 and x['C2']==0, axis=1).cumsum()+1

想要的結果:

   C1   C2  C3
0   0   0   1
1   0   0   1
2   1   0   2
3   1   1   2
4   1   1   2
5   0   1   2
6   0   0   2
7   0   0   2
8   0   0   2
9   1   0   3
10  1   1   3
11  1   1   3
12  0   1   3
13  0   0   3

你需要記住的:

當涉及到長數據時,不要使用 iterrows 它使它顯着變慢。

apply -- 比 iterrows 更好的替代品,而且效率更高

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM