[英]Pandas DataFrame: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
[英]Passing DataFrame slice as argument to function without 'SettingWithCopyWarning'
我有一個以數據框為參數的函數,在處理此數據框時,它調用另一個函數,該函數將同一數據框的一部分作為參數傳遞給輔助函數。
所有更改均已就位,因此不會返回任何內容(由於數據框的大小)。
但是,此輔助功能引發了SettingWithCopyWarning
因為它不再處理原始數據幀。
這是一個例子:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.arange(9).reshape(3,3), columns=list('abc'))
print df
def a(df):
if df.is_copy:
print 'a got a copy'
df['a'] = 'a'
def b(df):
if df.is_copy:
print 'b got a copy'
print df.is_copy
df.loc[:,'b'] = 'b'
def c(df):
a(df)
b(df.loc[0:1,:])
if df.is_copy:
print 'c got a copy'
df.loc[0:1,'c'] = 'c'
def d(df):
new_df = df.loc[0:1].copy(deep=True)
b(new_df)
df.update(new_df)
del new_df
c(df)
df
結果是:
b got a copy
<weakref at 000000000C1DE778; to 'DataFrame' at 000000000C1B9DA0>
a b c
0 a 1 c
1 a 4 c
2 a 7 8
我知道一種選擇是從原始切片創建一個新的數據幀,然后將其傳遞給b
,然后傳遞給df.update(new_df)
和d
表明它可以正常工作:
d(df)
df
產生所需的輸出:
a b c
0 a b c
1 a b c
2 a 7 8
但是有沒有一種方法可以解決此問題,而無需創建新的數據SettingWithCopyWarning
和提高SettingWithCopyWarning
。
另一個復雜之處是,有時從c
中調用b
可能只是簡單的b(df)
,所以切片是可選的。
謝謝。
如果要修改內容,最好只是傳遞框架和遮罩。
def b(df, row_mask):
df.loc[row_mask,'b'] = 'foo'
雖然通常我不會修改這樣的事情,尤其是如果它的框架很大。 當您更改dtypes時,這些修改會觸發一個副本(例如,通常不應該將“ b”放入所有數字的列中,dtypes是基於列的)。
因此,更好的工作流程是:
def b(df):
sliced = df.loc[0:1].copy()
sliced.loc[:,'b'] = 'foo'
return sliced
然后,您可以在結尾處簡單地包容:
result = pd.concat([b(df), df[1:]])
然后產生一個這樣的鏈,並立即連接在一起。 與就地修改相比,效率會更高(盡管如果您只修改少量值,那么我的第一種方法可能會更好地工作)。 YMMV。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.