熊猫填充模式

Posted

技术标签:

【中文标题】熊猫填充模式【英文标题】:How to Pandas fillna() with mode of column? 【发布时间】:2017-08-04 23:39:20 【问题描述】:

我有一个数据集,其中有一个名为 Native Country 的列,其中包含大约 30000 记录。缺少一些由NaN 表示的缺失,所以我想用mode() 值填充它。我写了这样的东西:

data['Native Country'].fillna(data['Native Country'].mode(), inplace=True)

但是,当我计算缺失值时:

for col_name in data.columns: 
    print ("column:",col_name,".Missing:",sum(data[col_name].isnull()))

它仍然为 Native Country 列提供相同数量的 NaN 值。

【问题讨论】:

你能发布原始数据、创建df的代码和你观察到的输出 data['Native Country'].mode() 返回一个系列对象。要访问它的第一个值,您需要在 fillna 操作期间包含 .iloc[0]。另请注意,如果该列中没有至少 2 次重复出现,NaN's 将不会被替换。 【参考方案1】:

只需调用系列的第一个元素:

data['Native Country'].fillna(data['Native Country'].mode()[0], inplace=True)

或者你也可以对分配做同样的事情:

data['Native Country'] = data['Native Country'].fillna(data['Native Country'].mode()[0])

【讨论】:

当然需要像mode()[0] 那样对单个数据列使用[0] 进行切片是一个错误:mode() 即使在系列上调用也假定一个DataFrame)。它应该像 mean() 一样工作,在 Series 上调用时返回单个浮点数,在 DataFrame 上调用时返回 Series ...不同行为的唯一理由是涵盖多模式分布。 很晚了。但是我有一个数据框,可以在其中合并多个数据库。有一个区域我必须使用分配方面或者我得到一个多索引警告,然后我运行一个函数来将这个系列与其他系列进行比较,我必须只使用 fillna(inplace=True) 或者一切都会改变而不是只是NaN。我不知道为什么【参考方案2】:

小心,NaN 可能是您的数据框的模式:在这种情况下,您将 NaN 替换为另一个 NaN。

【讨论】:

Pandas 0.24.0+ 默认不计算 NaN:pandas.pydata.org/pandas-docs/stable/reference/api/…【参考方案3】:

如果我们用fillna(df['colX'].mode()) 填充缺失值,由于mode() 的结果是一个Series,它只会填充匹配索引的前几行。至少如果按照以下方式完成:

fill_mode = lambda col: col.fillna(col.mode())
df.apply(fill_mode, axis=0)

但是,通过简单地取系列 fillna(df['colX'].mode()[0]) 的第一个值,我认为我们可能会在数据中引入意外的偏差。如果样本是多峰的,那么只取第一个众数会使已经有偏差的插补方法变得更糟。例如,如果我们有 [0, 21, 99] 作为同样最频繁的值,则仅采用 0。或者当TrueFalse 值在给定列中的频率相同时,用False 填充缺失值。

我在这里没有明确的解决方案。如果必须使用该模式,则从所有局部最大值中分配一个随机值可能是一种方法。

【讨论】:

【参考方案4】:

尝试类似: fill_mode = lambda col: col.fillna(col.mode()) 和功能: new_df = df.apply(fill_mode, axis=0)

【讨论】:

【参考方案5】:

您可以获取数字“模式”或任何其他策略

    对于模式:
    num = data['Native Country'].mode()[0]
    data['Native Country'].fillna(num, inplace=True)
    平均值、中位数:
    num = data['Native Country'].mean() #or median(); No need of [0] because it returns a float value.
    data['Native Country'].fillna(num, inplace=True)

或者像这样在一行中

data['Native Country'].fillna(data['Native Country'].mode()[0], inplace=True)

【讨论】:

【参考方案6】:
import numpy as np

import pandas as pd

print(pd.__version__)

1.2.0

df = pd.DataFrame('Country': [np.nan, 'France', np.nan, 'Spain', 'France'], 'Purchased': [np.nan,'Yes', 'Yes', 'No', np.nan])
Country Purchased
0 NaN NaN
1 France Yes
2 NaN Yes
3 Spain No
4 France NaN
 df.fillna(df.mode())  ## only applied on first row because df.mode() returns a dataframe with one row
Country Purchased
0 France Yes
1 France Yes
2 NaN Yes
3 Spain No
4 France NaN
df = pd.DataFrame('Country': [np.nan, 'France', np.nan, 'Spain', 'France'], 'Purchased': [np.nan,'Yes', 'Yes', 'No', np.nan])

df.fillna(df.mode().iloc[0]) ## convert df to a series
Country Purchased
0 France Yes
1 France Yes
2 France Yes
3 Spain No
4 France Yes

【讨论】:

【参考方案7】:

对于那些来到这里(就像我一样)在多列中填充 NA 的人,按多列分组,并且遇到模式不返回任何内容的问题,其中组中只有 NA 值:

df[['col_to_fill_NA_1','col_to_fill_NA_2']] = df.groupby(['col_to_group_by_1', 'col_to_group_by_2'], dropna=False)[['col_to_fill_NA_1','col_to_fill_NA_2']].transform(lambda x: x.fillna(x.mode()[0]) if len(x.mode()) == 1 else x)

您可以填写任意数量的“col_to_fill_NA”并按任意数量的“col_to_group_by”进行分组。 如果模式存在,if 语句返回模式并返回组的 NA,其中只有 NA。

【讨论】:

以上是关于熊猫填充模式的主要内容,如果未能解决你的问题,请参考以下文章

熊猫合并用空值填充新数据框

迭代填充空熊猫

熊猫:使用最后可用的填充缺失值

用值填充列(熊猫)

更改熊猫的轴替换填充

如何用随机字典值填充熊猫数据框列