pandas 如何更正此代码以不引发SettingWithCopyWarning?

5vf7fwbs  于 2023-06-20  发布在  其他
关注(0)|答案(1)|浏览(79)

我跟着这个-https://www.kdnuggets.com/2021/01/cleaner-data-analysis-pandas-pipes.html
大约在中途,作者创建了一个函数来删除异常值

def to_category(df):
    cols = df.select_dtypes(include='object').columns
    for col in cols:
        ratio = len(df[col].value_counts()) / len(df)
        if ratio < 0.05:
            df[col] = df[col].astype('category')
    return df

这引起了Python的警告--

Warning (from warnings module):
  File "D:/I7_Education/pandas_pipe_function1/pipes3.py", line 51
    df[col] = df[col].astype('category')
SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

我不确定我是否理解了问题所在(尽管我正在努力解决它,并在网上发布了一些帖子试图理解)。我还在试图理解文档的解释。
我知道我可以抑制来自Python的警告(如果抑制警告,代码可以正常运行)。我想知道如何更改文章中的代码,以便它不会首先引发警告。
我试图联系作者,但没有回音。
我想要的是不需要压制。但是我不明白问题是什么,不知道如何改变代码,使其不首先触发SettingWithCopyWarning。
我没想到你会警告我。文档以及一些在线帖子说要使用loc更改df,但我没有更改dataframe中的值或元素,而是将列的dtype从object更改为category; astype('catagory')是如何做到这一点的,我认为循环通过列来做到这一点应该没问题。一个朋友告诉我创建一个传递给函数的df的副本,然后操作它,然后返回副本,我也不完全理解,但它没有解决问题-它仍然引发相同的警告。
我传递给函数的 Dataframe 是一个副本。这篇文章只是在操纵数据集(directmarketing.csv);它将csv读入pandas Dataframe 并直接操作它。我创建了两个dataframe:第一个是dataset = pd.read_csv(".\directmarketing.csv"),第二个是marketing = dataset.copy(),我只是操纵营销 Dataframe 。这样我就可以回去检查数据集dataframe,并确保事情已经改变了他们应该的方式,等等。
但是当我调用这个函数时,我调用的是to_category(marketing)--我根本没有触及数据集dataframe。
在stackoverflow上有一个线程-Returning a copy versus a view warning when using Python pandas dataframe-讨论了这个问题,但是它说要 * 制作 * 一个副本来 * 避免 * 警告,所以我很困惑。
有没有一种方法可以纠正文章中的代码,使其不会触发此警告?谢谢你!
我使用的是Python 3.10和Idle-我没有使用IDE。

qni6mghb

qni6mghb1#

一个想法是通过DataFrame.astype重写解决方案,将final列表中的列名转换为dict.fromkeys的字典:

def to_category(df):
    final = []
    cols = df.select_dtypes(include='object').columns
    for col in cols:
        ratio = len(df[col].value_counts()) / len(df)
        if ratio < 0.05:
            final.append(col)
    return df.astype(dict.fromkeys(final, 'category'))

相关问题