在 pandas 1.5+ 中使用 .loc[:,'col'] 设置整个列(并更改数据类型)时出现问题

问题描述 投票:0回答:1

始终建议使用SettingWithCopy警告:

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**

因此,我开始使用

df.loc[:,'col'] = arr
来重新分配列,而不是
df['col'] = arr
。 但是,由于在 pandas 1.5.0 中实现了使用 .loc 和 .iloc 设置时的 changes 到就地操作,因此我使用
df.loc[:,'col'] = new_arr
的行为不一致,其中代码将在没有任何警告或错误的情况下执行,但列尝试将列转换为不同的数据类型时,类型未按预期修改。

例如,我有一个数据框weather_df,它在“year”列中读取数据类型为“float64”的数据(缺少默认为NaN的值)。

import pandas as pd
weather_df = pd.read_csv(weather_file)

我想用 0 填充缺失值,并将列 dtype 转换为“int32”。

以下代码静默执行,并将 NaN 值替换为 0,但不修改 pandas 1.5+ 的类型(weather_df['year].dtype 仍为 float64):

weather_df.loc[:,'year'] = weather_df['year'].fillna(0).astype('int32')

令人沮丧的是,以下代码确实修改了pandas 1.5+中的weather_df和'year'列值的数据类型,尽管以前不推荐这样做:

weather_df['year'] = weather_df['year'].fillna(0).astype('int32')

在最近的更改(1.4-)之前,这两行都会更新weather_df,我从文档中了解到,这两行应该继续工作,因为我正在设置整个列。它应该首先尝试就地操作,然后在就地操作因类型不匹配而失败时回退到转换(仅因为我要替换整个列),但 .loc[:,' 不会发生这种情况科尔']。

这是从现在开始的预期行为,还是一个错误?是否有解决方法可以使用 .loc 并获得旧的行为,或者我应该忘记有关使用 .loc 以避免链式分配的旧设置WithCopy 建议?

编辑:我使用 Python 版本 3.8.3 在 Linux x86_64 上运行此程序,并且任何版本 1.5.0 到 2.0.3(最新)都会出现错误。我还澄清了 fillna 似乎在这两种情况下都有效,但使用 .loc 时类型转换不起作用。

以下简化示例为我重现了该问题:

>>> df = pd.DataFrame({'col1':[20.,19.5,21.,24.,23.,22.], 'col2':[2020.,2021.,2022.,2023.,np.nan,2019.]})
>>> print(df['col2'].dtype)
float64
>>> df.loc[:,'col2'] = df['col2'].fillna(0).astype('int32')
>>> print(df['col2'].dtype)
float64
>>> df['col2'] = df['col2'].fillna(0).astype('int32')
>>> print(df['col2'].dtype)
int32
python pandas casting in-place pandas-loc
1个回答
0
投票

在 astype() 下的 docs 中有一个关于此的微妙注释:

当尝试使用以下方法将列的子集转换为指定类型时 astype() 和 loc(),会发生向上转换。

loc() 尝试适应我们分配给当前数据类型的内容, 而 [] 将从右侧获取 dtype 来覆盖它们 侧面。

旧版本的 pandas 也出现了同样的问题(请参阅关于 pandas 0.18 的这篇文章)。在某些时候(我无法确定何时),这被更改为 df.loc[:,'col'] 和 df['col'] 在使用 .astype() 转换列时产生相同的结果到一个新的类型。我知道这一点是因为 pandas 版本 1.2-1.4(至少)产生了我预期的结果,其中 df['col'].dtype 已更新,无论 df.loc[:,'col'] 或 df['col'] 是否已更新用在作业的左侧。

但是,在 pandas 版本 1.5-2.0.3(Windows/Linux、Python 3.8)中,这种情况再次发生了变化,loc() 和 astype() 交互遵循文档中的微妙注释(请参阅this post 关于 pandas 2.0) .0).

我觉得这种行为应该发出警告,通知用户使用 .loc[] 进行的预期类型转换失败。我将在 pandas-dev GitHub 上提出问题并用链接更新此答案。

© www.soinside.com 2019 - 2024. All rights reserved.