我正在关注: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 ,但我没有更改数据框中的值或元素,而是将列的 dtype 从对象更改为类别;
astype('catagory')
是如何做到这一点,我认为循环遍历列来做到这一点应该没问题。一位朋友告诉我创建传递给函数的 df 的副本,然后对其进行操作,然后返回副本,我也不完全理解,但它并没有解决问题 - 它仍然引发相同的问题警告。
我传递给函数的数据帧是一个副本。文章仅操作数据集(directmarketing.csv);它将 csv 读入 pandas 数据帧并直接操作它。相反,我创建了两个数据框:第一个是
dataset = pd.read_csv(".\directmarketing.csv")
,第二个是 marketing = dataset.copy()
,我只是操作营销数据框。这样我就可以返回并检查数据集数据框,并确保事情已经按照预期的方式改变,等等。
但是当我调用该函数时,我正在调用
to_category(marketing)
- 我根本没有触及数据集数据框。
stackoverflow 上有一个线程 - 使用 Python pandas dataframe 时返回副本与视图警告 - 谈到了这一点,但它说要 make 一个副本来避免警告,所以我非常困惑。
有没有办法更正文章中的代码,使其不会引发此警告?
我正在使用 Python 3.10,并且处于空闲状态 - 我没有使用 IDE。
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'))