熊猫:自定义分组功能

时间:2018-12-29 14:44:26

标签: python pandas group-by

我正在寻找一个自定义分组依据函数,该函数将以以下方式对行进行分组:

  • 如果有任何数字和0,它将加上数字。
  • 如果有两个数字(它们始终都相同),则它将相加。
  • 如果有一个NaN和一个NaN,它将添加一个NaN。
  • 如果有一个数字和一个NaN,它将添加该数字。

使事情更清晰的示例:

start_df = pd.DataFrame({"id": [1,1,2,2,3,3,4,4,4,5],
                         "foo": [4, 4, np.nan, 7, np.nan, np.nan, 0, 9, 9, 7],
                         "bar": [np.nan, np.nan, 0, 4, 0, 1, 6, 6, 0, 4]})

    id  foo  bar
0   1   4.0  NaN
1   1   4.0  NaN
2   2   NaN  0.0
3   2   7.0  4.0
4   3   NaN  0.0
5   3   NaN  1.0
6   4   0.0  6.0
7   4   9.0  6.0
8   4   9.0  0.0
9   5   7.0  4.0

自定义分组依据之后,id

result_df = pd.DataFrame({"id": [1,2,3,4,5], "foo": [4, 7, np.nan, 9, 7], "bar": [np.nan, 4, 1, 6, 4]})


    id  foo  bar
0   1   4.0  NaN
1   2   7.0  4.0
2   3   NaN  1.0
3   4   9.0  6.0
4   5   7.0  4.0

我知道的一个解决方案是:

start_df.groupby("id").max().reset_index()

但是对于我来说情况太慢了,因为我要处理的数据帧很大。另一方面,我无法用这种解决方案来说明两个元素都是数字的极端情况:

start_df.groupby("id").sum(min_count=1).reset_index()

期待您的帮助!

3 个答案:

答案 0 :(得分:2)

也许不是您原本想的那样,但这应该可行

start_df.groupby('id').max()

如果要将“ id”重新添加到列中,请使用reset_index

答案 1 :(得分:0)

我相信您正在寻找的解决方案非常理想。

我在下面添加了另一种方法,在groupby中指定as_index=False可以使用groupby.GroupBy.nth保留原始索引

>>> start_df.groupby('id',  as_index=False).nth(1)
   id  foo  bar
1   1  4.0  NaN
3   2  7.0  4.0
5   3  NaN  1.0
7   4  9.0  6.0

OR

>>> start_df.groupby(['id'], sort=False).max().reset_index()
   id  foo  bar
0   1  4.0  NaN
1   2  7.0  4.0
2   3  NaN  1.0
3   4  9.0  6.0

答案 2 :(得分:0)

这是不使用groupby的另一种方法,但我不能确定它是否更有效。想法是每个id具有相同的行数,以便能够reshape数据并在轴上使用np.nanmax。为此,您可以生成缺失值为nan的数据框。

#create the count of each id
s = start_df.id.value_counts()
nb_max = s.max()
#ceate the dataframe with nan
df_nan = pd.DataFrame({col: np.nan if col != 'id' 
                                   else [ids for ids, val in zip(s.index,nb_max-s.values) 
                                             for _ in range(val)] 
                       for col in start_df.columns })
#get the result
result_df = pd.DataFrame( np.nanmax( pd.concat([start_df, df_nan])[start_df.columns]
                                       .sort_values('id').values
                                       .reshape((-1,start_df.shape[1],nb_max)), 
                                     axis=1), 
                          columns = start_df.columns)

注意:您会收到一条警告,指出某些切片只是nan,但它可以起作用,可能有一种方法可以使此警告静音。