2017-10-19 28 views
0

我試圖用熊貓pd.DataFrame.where如下:替代有效的方法大熊貓在那裏

df.where(cond=mask, other=df.applymap(f)) 

f是一個用戶定義的函數,在單個細胞進行操作。我不能使用other=f,因爲它似乎產生了不同的結果。

所以基本上我想在DataFrame的所有單元格中評估函數f,它不滿足某些條件,我將它作爲mask給出。

使用where是不是很有效,因爲它立即評估f整個數據幀df,而我只需要在數據幀的一些條目,以評估它有時可以是非常少數的特定條目相比,整個以上使用數據幀。

在解決這種一般情況時,是否有另一種用法/方法更有效?

+2

您能否提供示例數據和函數定義? – skrubber

+0

你不能修改f嗎?如果沒有,'df.applymap(lambda x:f(x)if cond else x)'應該不需要在哪裏做。 – ayhan

回答

1

正如你所說的,df.applymap(f)df.where()之前被評估。我相當肯定df.where()是一個快速功能,並不是這裏的瓶頸。

這很可能是df.applymap(f)效率低下,並且通常以更快的方式以向量化方式執行f。話雖如此,如果你確實認爲這是不可能的,並且f本身就很慢,你可以修改f以保持輸入不變,無論你的掩碼是False。儘管這很可能會非常慢,並且您肯定會更喜歡嘗試使用向量化來代替f。

如果你真的必須這樣做逐元素,你可以使用NumPy的數組:

result = df.values 
for (i,j) in np.where(mask): 
    result[i,j] = f(result[i,j]) 

這是至關重要的,你使用NumPy的陣列對於這一點,而不是在數據幀.iloc.loc,因爲索引熊貓數據框很慢。

您可以將本項速度與.applymap進行比較;對於相同的操作,我不認爲.applymap比簡單的for循環要快得多(如果有的話),因爲所有的熊貓都是在Python中運行一個自己的for循環(也許是Cython?但是即使那樣只會節省開銷,而不是函數本身)。這與「正確的」矢量化不同,因爲矢量操作在C中實現。

+0

'你可以修改f以保持輸入不變,無論你的掩碼是否爲假,這正是我正在尋找的。你會如何實現這一目標? – user113531

+0

我實際上是假設你的布爾掩碼只取決於你的數據的值,這可能不是這種情況。如果確實不是這樣,那麼沒有一些荒謬的全局變量的使用是不可能的。這是因爲'.applymap'只將值(而不是索引)傳遞給'f'。 –