【问题标题】:Python ColumnTransformer SettingWithCopyWarningPython ColumnTransformer SettingWithCopyWarning
【发布时间】:2020-04-21 23:09:05
【问题描述】:

我在使用 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)

我已经设法通过稍微更改fill_nan() 函数来修复它,但我不明白为什么会修复它。

def filling_nan(frame):
    """Fills columns that have null values with zeros."""
    frame = frame.fillna(0)
    return frame

我无法在使用 ColumnTransformer 之外重现结果,所以想知道这是否与此有关?

【问题讨论】:

    标签: python pandas numpy dataframe scikit-learn


    【解决方案1】:

    我相信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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-28
      • 2019-08-31
      • 2016-10-31
      • 1970-01-01
      • 2021-06-17
      • 2020-06-30
      • 2020-05-20
      • 2022-10-04
      相关资源
      最近更新 更多