我有一个问题,当使用scikit-learn ColumnTransformer将转换应用于DataFrame时,会收到SettingWithCopyWarning,但我不确定为什么会这样。
这是我的代码。
import pandas as pd
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import FunctionTransformer
import warnings
warnings.filterwarnings("always")
def filling_nan(frame):
"""Fills columns that have null values with zeros."""
frame.fillna(0, inplace=True)
return frame
def as_is(frame):
"""Returns the DataFrame as it is."""
return frame
np.random.seed(1337)
df = pd.DataFrame(data=np.random.random(size=(5,5)), columns=list('ABCDE'))
df = df.applymap(lambda x: np.nan if x<0.15 else x) # Set a few numbers in the dataframe to NaN.
print(df)
这就是原始DataFrame的样子...
A B C D E
0 0.262025 0.158684 0.278127 0.459317 0.321001
1 0.518393 0.261943 0.976085 0.732815 NaN
2 0.386275 0.628501 NaN 0.983549 0.443225
3 0.789558 0.794119 0.361262 0.416104 0.584258
4 0.760172 0.187808 0.288167 0.670219 0.499648
然后,我在ColumnTransformer中创建步骤,并指定列的索引而不是列名。
step_filling_nans = ('filling_nans', FunctionTransformer(filling_nan, validate=False), [2, 4])
step_as_is = ('as_is', FunctionTransformer(as_is, validate=False), [0, 1, 3])
然后创建ColumnTransformer ...
trans = ColumnTransformer(
transformers=[
step_filling_nans
, step_as_is # I could pass 'passthrough' to the remainder keyword instead of doing this step.
], remainder='drop')
最后,我将将ColumnTransformer应用于我的DataFrame的结果打印出来。
print(trans.fit_transform(df))
这是转换的输出。 ColumnTransformer返回一个预期的numpy数组(分别在第一和第二列分别为'C'和'E'列),但我不明白为什么会收到SettingWithCopy警告。
[[0.27812652 0.32100054 0.26202468 0.15868397 0.45931689]
[0.97608528 0. 0.51839282 0.26194293 0.73281455]
[0. 0.44322487 0.38627507 0.62850118 0.98354861]
[0.36126157 0.58425813 0.78955834 0.79411858 0.41610394]
[0.28816715 0.49964826 0.76017177 0.18780841 0.67021886]]
/bigdisk0/users/belladam/.conda/envs/day_zero_retention/lib/python3.6/site-packages/pandas/core/frame.py:3787: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
downcast=downcast, **kwargs)
我设法通过稍微更改filling_nan()函数来修复它,但是我不明白为什么要修复它。
def filling_nan(frame):
"""Fills columns that have null values with zeros."""
frame = frame.fillna(0)
return frame
我一直无法在使用ColumnTransformer之外重现结果,所以想知道是否与此有关吗?
最佳答案
我相信ColumnTransformer
的行为方式是因为它能够并行运行与不同列相关的不同转换。您可以看一下第448行的sklearn code itself here。如果要使用并行化,那么对同一对象(相同的内存位置)进行操作并不是很安全。
通过避免使用inplace
,您实际上是在处理原始对象的副本,从而解决了这个问题:
def filling_nan(frame):
"""Fills columns that have null values with zeros."""
frame = frame.fillna(0)
return frame
def filling_nan_inplace(frame):
"""Fills columns that have null values with zeros."""
frame.fillna(0, inplace=True)
return frame
print(id(df))
print(id(filling_nan_inplace(df)))
print(id(filling_nan(df)))
输出:
2088604584760
2088604584760
2088604583304
关于python - Python ColumnTransformer SettingWithCopyWarning,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59577674/