熊猫不会在原地填写na()

Posted

技术标签:

【中文标题】熊猫不会在原地填写na()【英文标题】:Pandas won't fillna() inplace 【发布时间】:2014-03-26 17:46:53 【问题描述】:

我正在尝试在数据框中的 4 个特定列上用“”填充 NA,这些列是字符串/对象类型。我可以在 fillna() 时将这些列分配给一个新变量,但是当我 fillna() 就地时,基础数据不会改变。

a_n6 = a_n6[["PROV LAST", "PROV FIRST", "PROV MID", "SPEC NM"]].fillna("")
a_n6

给我:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 1542 entries, 0 to 3611
Data columns (total 4 columns):
PROV LAST     1542  non-null values
PROV FIRST    1542  non-null values
PROV MID      1542  non-null values
SPEC NM       1542  non-null values
dtypes: object(4)

但是

a_n6[["PROV LAST", "PROV FIRST", "PROV MID", "SPEC NM"]].fillna("", inplace=True)
a_n6

给我:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 1542 entries, 0 to 3611
Data columns (total 7 columns):
NPI           1103  non-null values
PIN           1542  non-null values
PROV FIRST    1541  non-null values
PROV LAST     1542  non-null values
PROV MID      1316  non-null values
SPEC NM       1541  non-null values
flag          439  non-null values
dtypes: float64(2), int64(1), object(4)

这只是一排,但仍然令人沮丧。我做错了什么?

【问题讨论】:

我也遇到过一些inplace=True 似乎被忽略的函数。虽然这不是您的问题,但在进行故障排除时值得牢记。 【参考方案1】:

您正在填写一份副本(然后您看不到)

要么:

不要fillna inplace(就地做某事不会提高性能)

例如

a_n6[["PROV LAST", "PROV FIRST", "PROV MID", "SPEC NM"]] = a_n6[["PROV LAST", "PROV FIRST", "PROV MID", "SPEC NM"]].fillna("")

或者最好

a_n6.fillna('PROV LAST': '', 'PROV FIRST': '',
            'PROV MID': '', 'SPEC NM': '', inplace=True)
首先将副本分配给新变量(a_n6[[list_of_fileds]] 是多类型对象中的副本),请参见此处:http://pandas.pydata.org/pandas-docs/stable/indexing.html#returning-a-view-versus-a-copy

这里有更深入的解释 Pandas: Chained assignments

【讨论】:

我认为 inplace 参数应该防止它填充副本。如果 inplace arg 不改变函数的行为,它的意义何在? 那么为什么 fillna() 甚至允许 inplace 呢? 如果您使用 .loc,Inplace 将起作用。如果您正在处理副本,则 Inplace 不应该工作。请参阅 Jeff 包含的链接。它不适用于字段列表(例如 df.loc[:,[list of fields]]),但适用于切片或单个字段。另请参阅github.com/pandas-dev/pandas/issues/11984 了解有关此的一些详细信息。 我刚刚在一个 20Gb 数据集上运行了 fillna,就地并得到了“未实现”错误。我没有看到关于“没有性能提升”的咆哮。我没有另一个 20Gb 内存来保存临时副本。 Inplace 将非常有益。【参考方案2】:

使用dict 作为value 的参数fillna()

正如@rhkarls 对@Jeff 的回答的评论中提到的,使用索引到列列表的.loc 将不支持inplace 操作,我也觉得这很令人沮丧。这是一种解决方法。

例子:

import pandas as pd
import numpy as np

df = pd.DataFrame('a':[1,2,3,4,np.nan],
                   'b':[6,7,8,np.nan,np.nan],
                   'x':[11,12,13,np.nan,np.nan],
                   'y':[16,np.nan,np.nan,19,np.nan])
print(df)
#     a    b     x     y
#0  1.0  6.0  11.0  16.0
#1  2.0  7.0  12.0   NaN
#2  3.0  8.0  13.0   NaN
#3  4.0  NaN   NaN  19.0
#4  NaN  NaN   NaN   NaN

假设我们只想为xy 发送fillna不是 ab

我希望使用 .loc 可以工作(就像在作业中一样),但它没有,如前所述:

# doesn't work
df.loc[:,['x','y']].fillna(0, inplace=True)
print(df) # nothing changed

但是,documentation 表示 fillna()value 参数可以是:

或者是一个 dict/Series/DataFrame 值,指定用于每个索引(对于 Series)或列(对于 DataFrame)的值。 (不在 dict/Series/DataFrame 中的值不会被填充)。

事实证明,使用值的字典会起作用:

# works
df.fillna('x':0, 'y':0, inplace=True)
print(df)
#     a    b     x     y
#0  1.0  6.0  11.0  16.0
#1  2.0  7.0  12.0   0.0
#2  3.0  8.0  13.0   0.0
#3  4.0  NaN   0.0  19.0
#4  NaN  NaN   0.0   0.0

另外,如果您的子集中有很多列,您可以使用字典推导式,如下所示:

df.fillna(x:0 for x in ['x','y'], inplace=True) # also works

【讨论】:

【参考方案3】:

一种解决方法是将 fillna 结果保存在另一个变量中,然后像这样将其分配回去:

na_values_filled = X.fillna(0)
X = na_values_filled

我的确切示例(否则我无法开始工作)是我只想填写每个组的第一行的情况。像这样:

groups = one_train.groupby("installation_id")
first_indexes_filled = one_train.loc[groups.apply(pd.DataFrame.first_valid_index), 'clicks'].fillna(0)
one_train.loc[groups.apply(pd.DataFrame.first_valid_index), 'clicks'] =  first_indexes_filled

我的情况可能过于复杂,但我认为一般的“保存结果,然后分配回”方法应该可以作为失败的 inplace=True 的解决方法

【讨论】:

【参考方案4】:

最佳答案给了我SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame,所以这就是我最终得到的。它可以工作并且不会发出任何警告:

fill_dict = x: 0 for x in columns_of_interest
df.loc[:, columns_of_interest].fillna(fill_dict, inplace=True)

【讨论】:

【参考方案5】:

“使用 dict 作为值参数”答案对我不起作用,但一个足够简单的解决方法是使用:

for n in ["PROV LAST", "PROV FIRST", "PROV MID", "SPEC NM"]:    
    a_n6[n].fillna("", inplace=True)
a_n6

【讨论】:

以上是关于熊猫不会在原地填写na()的主要内容,如果未能解决你的问题,请参考以下文章

在熊猫数据框中添加随机噪声和随机 NA

熊猫的 pd.NA 与 np.nan

为啥在数据帧上具有中位数的 fillna 仍然在熊猫中留下 Na/NaN?

熊猫:用组的模式填充na

python 熊猫 - 掉落NA(NaN)

从 Google BigQuery 创建熊猫数据框时如何执行 na_values