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
def 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]
7条答案
按热度按时间9w11ddsr1#
pandas >= 1.1
从pandas 1.1开始,你可以更好地控制这种行为,现在在grouper中允许使用**
dropna=False
**的NA值:个字符
mwecs4sa2#
这在文档的缺失数据部分中提到:
GroupBy中的NA组被自动排除。
一种解决方法是在执行groupby之前使用占位符(例如-1):
字符串
hgncfbus3#
这是一个古老的主题,如果有人仍然对此感到困惑,另一个解决方法是在分组之前将via .astype(str)转换为字符串。
个字符
gupuwyp24#
我不能给M. Kiewisch添加评论,因为我没有足够的声誉点(只有41点,但需要超过50点才能评论)。
无论如何,只是想指出,M. Kiewisch解决方案并不像现在这样工作,可能需要更多的调整。
字符串
这表明,对于组B=4.0,对应的值是15而不是6。这里只是将1和5作为字符串连接起来,而不是将其作为数字相加。
0ejtzxu15#
到目前为止提供的所有答案都会导致潜在的危险行为,因为您很可能选择了一个实际上是数据集一部分的虚拟值。当您创建具有许多属性的组时,这种可能性越来越大。简单地说,这种方法并不总是很好地泛化。
一个不那么麻烦的解决方案是使用pd.drop_duplicates()来创建一个唯一的值组合索引,每个值组合都有自己的ID,然后根据该ID进行分组。它更详细,但确实完成了工作:
字符串
请注意,您现在可以简单地执行以下操作:
型
这将返回成功的结果,而不必担心错误的真实的数据被误认为虚拟值。
vs91vp4v6#
Andy Hayden的解决方案的一个小问题-它不工作(不再?)因为
np.nan == np.nan
产生False
,所以replace
函数实际上没有做任何事情。对我起作用的是:
字符串
(At至少这是Pandas 0.19.2的行为。抱歉添加它作为不同的答案,我没有足够的声誉来评论。)
pbpqsu0x7#
我已经回答了这个问题,但由于某种原因,答案被转换为评论。然而,这是最有效的解决方案:
不能在组中包含(和传播)NaN是相当令人恼火的。引用R是没有说服力的,因为这种行为与许多其他事情不一致。无论如何,虚拟黑客也很糟糕。然而,如果有NaN,组的大小(包括NaN)和计数(忽略NaN)会有所不同。
字符串
当这些值不同时,您可以将该组的聚合函数结果的值设置回None。