我有一个问题,当使用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/

10-11 15:43