用Nan值计算最常出现的人群

时间:2018-07-02 08:44:00

标签: python pandas dataframe scipy pandas-groupby

基本上,我想计算按2个变量分组的最频繁项的数量。我使用以下代码:

dfgrouped = data[COLUMNS.copy()].groupby(['Var1','Var2']).agg(lambda x: stats.mode(x)[1])

此代码有效,但不适用于具有Nan值的列,因为NaN值是浮点型而其他是str。因此显示此错误:

'<' not supported between instances of 'float' and 'str'

我想忽略其余的NaN值和计数模式。所以str(x)不是解决方案。 scipy.stats.mode(x,nan_policy ='omit')也不起作用,并且出现错误:

TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

请您给我一个建议,以解决该问题。 谢谢

3 个答案:

答案 0 :(得分:1)

我认为需要dropna才能删除NaN

dfgrouped = data[COLUMNS.copy()].groupby(['Var1','Var2']).agg(lambda x: stats.mode(x.dropna())[1])

如果需要为所有NaN组设置NaN

dfgrouped = (data[COLUMNS.copy()]
              .groupby(['Var1','Var2'])
              .agg(lambda x: None if x.isnull().all() else stats.mode(x.dropna())[1]))

答案 1 :(得分:1)

dropna first

您可以先执行dropna,然后再执行groupby。如果尝试在聚合中进行dropna,则具有所有NaN值的组可能会产生stats.mode的错误。

这是一个最小的例子:

import pandas as pd
import numpy as np
from scipy import stats

df = pd.DataFrame([[1, 2, np.nan], [1, 2, 'hello'], [1, 2, np.nan],
                   [5, 6, 'next'], [5, 6, np.nan], [5, 6, 'next'],
                   [7, 8, np.nan], [7, 8, np.nan], [7, 8, np.nan]],
                  columns=['Var1', 'Var2', 'Value'])

res = df.dropna(subset=['Value'])\
        .groupby(['Var1', 'Var2'])\
        .agg(lambda x: stats.mode(x)[1][0])

print(res)

           Value
Var1 Var2       
1    2         1
5    6         2

捕获IndexError

如果您需要保留包含所有NaN值的组,则可以捕获IndexError

def mode_calc(x):
    try:
        return stats.mode(x.dropna())[1][0]
    except IndexError:
        return np.nan

res = df.groupby(['Var1', 'Var2'])\
        .agg(mode_calc)

print(res)

           Value
Var1 Var2       
1    2       1.0
5    6       2.0
7    8       NaN

答案 2 :(得分:0)

nan的类型为float并且np.nan == np.nan也是False。如果需要将它们分组在一起,可以尝试如下操作:

# First replace nan values with something like 'Unavailable'
data.fillna('Unavailable', inplace=True)
# Then re-run your code
dfgrouped = data[COLUMNS.copy()].groupby(['Var1','Var2']).agg(lambda x: stats.mode(x)[1])

这会将所有不可用项分组在一起。希望有帮助