Pandas: 填充 NaN 值

11

我有一个不完整的数据框,incomplete_df,如下所示。我想用相应id的平均金额来填充缺失的amount。 如果该特定id的平均值本身为NaN(见id=4),我希望使用总体平均值。

以下是示例数据和我极低效的解决方案:

import pandas as pd
import numpy as np
incomplete_df = pd.DataFrame({'id': [1,2,3,2,2,3,1,1,1,2,4],
                              'type': ['one', 'one', 'two', 'three', 'two', 'three', 'one', 'two', 'one', 'three','one'],
                         'amount': [345,928,np.NAN,645,113,942,np.NAN,539,np.NAN,814,np.NAN] 
                         }, columns=['id','type','amount'])

# Forrest Gump Solution
for idx in incomplete_df.index[np.isnan(incomplete_df.amount)]: # loop through all rows with amount = NaN
    cur_id = incomplete_df.loc[idx, 'id']
    if (cur_id in means.index ):
        incomplete_df.loc[idx, 'amount'] = means.loc[cur_id]['amount'] # average amount of that specific id.
    else:
        incomplete_df.loc[idx, 'amount'] = np.mean(means.amount) # average amount across all id's

最快、最pythonic/pandonic的实现方式是什么?


在0.13版本中,您可以使用以下方法:http://pandas.pydata.org/pandas-docs/dev/missing_data.html#interpolation 并查看缺失值部分:http://pandas.pydata.org/pandas-docs/dev/missing_data.html#cleaning-filling-missing-data - Jeff
1
@Jeff,谢谢。但是我拥有的不是时间序列。因此,从统计学角度来看,我正在寻找插值而不是内插或外推。如果给定 ID 的平均值本身为NaN,我该如何处理这种情况? - Zhubarb
请参考下面的@DSM解决方案,这可能是您想要的。但插值可以在帧上工作,时序是无关紧要的。有许多选项可供选择。 - Jeff
@Jeff,你的章节链接现在是https://pandas-docs.github.io/pandas-docs-travis/missing_data.html#cleaning-filling-missing-data。另外,将OP的评论添加到文档中会很有帮助:pandas插补不仅适用于时间序列,而且应避免使用“向后”、“向前”等术语(只需说“缺失”)非连续、非时间序列数据。此外,有用的是指出pandas仅提供单一插补,而不是多重插补;请参见第三方软件包,如`fancyimpute`等。 - smci
1个回答

23
免责声明:我并不是真正对最快的解决方案感兴趣,而是对最具可操作性的方案感兴趣。

这里,我认为应该是这样的:


这里,我认为应该是这样的:

>>> df["amount"].fillna(df.groupby("id")["amount"].transform("mean"), inplace=True)
>>> df["amount"].fillna(df["amount"].mean(), inplace=True)

生产

>>> df
    id   type  amount
0    1    one   345.0
1    2    one   928.0
2    3    two   942.0
3    2  three   645.0
4    2    two   113.0
5    3  three   942.0
6    1    one   442.0
7    1    two   539.0
8    1    one   442.0
9    2  three   814.0
10   4    one   615.2

[11 rows x 3 columns]

根据您想要进行的链式插补过程的具体方式,有很多明显的微调可以进行。


谢谢 DSM,如果我在NaN的位置上有一个占位符,例如0,那么最快的方法是将所有0替换回NaN,然后按照您的解决方案进行操作吗?(我知道用0代替NaN是一个愚蠢的想法 - 不幸的是,我所拥有的就是我必须处理的。) - Zhubarb
1
这可能是我会做的事情。在pandas中,使用NaN来表示缺失数据非常深入,因此通常最简单的本地方法需要将您的数据与之对齐。我不知道最快的方法 - 您可以使用timeit进行比较。无论如何,将0替换为NaN都将是线性和矢量化的,因此它不会增加运行时间。 - DSM
1
只是确认一下,这是两个选择,而不是都必须完成单个操作吗? - 3pitt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接