Pandas不会在适当的地方填

omvjsjqw  于 2023-03-28  发布在  其他
关注(0)|答案(5)|浏览(156)

我尝试在数据框中的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)

只是一排,但还是让人沮丧。我做错了什么?

holgip5t

holgip5t1#

使用dict作为fillna()value参数

正如@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

假设我们只想将fillna用于xy而不是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中的值将不会被填充)。
事实证明,使用值的dict将起作用:

# 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

此外,如果你的子集中有很多列,你可以使用dict解析,如:

df.fillna(dict.fromkeys(['x', 'y'], 0), inplace=True) # also works
mbjcgjjk

mbjcgjjk2#

你正在填写一个副本(然后你看不到)
或者:

  • 不要就地执行fillna(就地执行某些操作不会提高性能)

例如

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]]是multi-dtype对象中的副本),参见此处:http://pandas.pydata.org/pandas-docs/stable/indexing.html#returning-a-view-versus-a-copy

下面是对Pandas更深入解释:链式赋值

kiayqfof

kiayqfof3#

解决方法是将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的解决方案

lmvvr0a8

lmvvr0a84#

最上面的答案给了我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)
xdnvmnnf

xdnvmnnf5#

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

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

相关问题