import pandas as pd
import numpy as np
df = pd.DataFrame({'a': ['1', '2', '3'], 'b': ['4', np.NaN, '6']})
In [4]: df.groupby('b').groups
Out[4]: {'4': [0], '6': [2]}
看到Pandas已经删除了具有NaN目标值的行。我想要包括这些行!有什么建议吗?
import pandas as pd
import numpy as np
df = pd.DataFrame({'a': ['1', '2', '3'], 'b': ['4', np.NaN, '6']})
In [4]: df.groupby('b').groups
Out[4]: {'4': [0], '6': [2]}
从pandas 1.1版本开始,您可以更好地控制此行为,使用dropna=False
,在分组器中现在允许NA值:
pd.__version__
# '1.1.0.dev0+2004.g8d10bfb6f'
# Example from the docs
df
a b c
0 1 2.0 3
1 1 NaN 4
2 2 1.0 3
3 1 2.0 2
# without NA (the default)
df.groupby('b').sum()
a c
b
1.0 2 3
2.0 2 5
# with NA
df.groupby('b', <b>dropna=False</b>).sum()
a c
b
1.0 2 3
2.0 2 5
NaN 1 4
kroscek_jupyter_metabase = fromdb_1474_detail.groupby(groupby, dropna = False)[col_to_count].count()
返回 TypeError: groupby() got an unexpected keyword argument 'dropna'
。 - CignitorGroupBy中的NA组会自动被排除。这种行为与R一致。
一个解决方法是在进行GroupBy之前使用占位符(例如-1):
In [11]: df.fillna(-1)
Out[11]:
a b
0 1 4
1 2 -1
2 3 6
In [12]: df.fillna(-1).groupby('b').sum()
Out[12]:
a
b
-1 2
4 1
6 3
话虽如此,这种感觉非常糟糕的hack...也许应该有一个选项来包括NaN在groupby中(请参见this github issue - 它使用相同的占位符hack)。
然而,正如另一个答案中所描述的那样,“从pandas 1.1开始,您可以更好地控制此行为,使用dropna=False允许在分组器中使用NA值。”
古老的话题,如果有人仍然遇到这个问题——另一个解决方法是在分组之前通过.astype(str)将其转换为字符串。这将保留 NaN 值。
df = pd.DataFrame({'a': ['1', '2', '3'], 'b': ['4', np.NaN, '6']})
df['b'] = df['b'].astype(str)
df.groupby(['b']).sum()
a
b
4 1
6 3
nan 2
a
的“和”指的是字符串连接,而不是数值相加。这种做法只能在'b'的条目各不相同的情况下“奏效”。你需要将'a'转换为数字,并将'b'转换为字符串。 - BallpointBena
是一个对象,在groupby
之后得到的平均值可能不是您想要的东西!!!!! - Jason Goal由于我没有足够的声望积分(只有41分,但需要超过50分才能发表评论),因此无法向M. Kiewisch添加评论。
无论如何,我只想指出M. Kiewisch的解决方案并不起作用,可能需要更多的调整。例如考虑
>>> df = pd.DataFrame({'a': [1, 2, 3, 5], 'b': [4, np.NaN, 6, 4]})
>>> df
a b
0 1 4.0
1 2 NaN
2 3 6.0
3 5 4.0
>>> df.groupby(['b']).sum()
a
b
4.0 6
6.0 3
>>> df.astype(str).groupby(['b']).sum()
a
b
4.0 15
6.0 3
nan 2
这表明当 b=4.0 时,相应的值为15而不是6。在这里,只是将1和5作为字符串连接起来,而不是将它们作为数字相加。
b
列。 - Koremdef safe_groupby(df, group_cols, agg_dict):
# set name of group col to unique value
group_id = 'group_id'
while group_id in df.columns:
group_id += 'x'
# get final order of columns
agg_col_order = (group_cols + list(agg_dict.keys()))
# create unique index of grouped values
group_idx = df[group_cols].drop_duplicates()
group_idx[group_id] = np.arange(group_idx.shape[0])
# merge unique index on dataframe
df = df.merge(group_idx, on=group_cols)
# group dataframe on group id and aggregate values
df_agg = df.groupby(group_id, as_index=True)\
.agg(agg_dict)
# merge grouped value index to results of aggregation
df_agg = group_idx.set_index(group_id).join(df_agg)
# rename index
df_agg.index.name = None
# return reordered columns
return df_agg[agg_col_order]
data_block = [np.tile([None, 'A'], 3),
np.repeat(['B', 'C'], 3),
[1] * (2 * 3)]
col_names = ['col_a', 'col_b', 'value']
test_df = pd.DataFrame(data_block, index=col_names).T
grouped_df = safe_groupby(test_df, ['col_a', 'col_b'],
OrderedDict([('value', 'sum')]))
对于 Andy Hayden 的解决方案,有一个小问题 - 它不再起作用了吗?因为 np.nan == np.nan
的结果是 False
,所以 replace
函数实际上并没有起到任何作用。
对我而言,下面的方法可以解决这个问题:
df['b'] = df['b'].apply(lambda x: x if not np.isnan(x) else -1)
df['b'].fillna(-1)
。 - K3---rnc我已经回答过这个问题了,但由于某些原因,答案被转换为评论。尽管如此,这是最有效的解决方案:
不能在组中包含(和传播)NaNs非常令人恼火。引用R并不令人信服,因为这种行为与许多其他事物不一致。无论如何,虚拟操作也很糟糕。然而,如果存在NaN,则组的大小(包括NaN)和计数(忽略NaN)将不同。
dfgrouped = df.groupby(['b']).a.agg(['sum','size','count'])
dfgrouped['sum'][dfgrouped['size']!=dfgrouped['count']] = None
如果这些值不同,您可以将聚合函数的结果值设为 None。
groupby()
中指定dropna=False
以获得所需的结果。更多信息 - cs95dropna=False
无法正常工作。在他们的Github上有一些提到这个问题的未解决问题,并且目前还没有太多修复的动力,不幸的是。 - totalhack