使用多列的 Pandas groupby 函数

Posted

技术标签:

【中文标题】使用多列的 Pandas groupby 函数【英文标题】:Pandas groupby function using multiple columns 【发布时间】:2018-12-20 03:23:26 【问题描述】:

这类似于以下内容,但我想进一步提出一个问题: pandas groupby apply on multiple columns to generate a new column

我有这个数据框:

    Group  Value  Part    Ratio
0     A    6373    10    0.637300
1     A    2512    10    0.251200
2     A    603     10    0.060300
3     A    512     10    0.051200
4     B    5200    20    0.472727
5     B    4800    20    0.436364
6     B    501     20    0.045545
7     B    499     20    0.045364

这个函数同时使用了我想应用于每个“组”的“比率”和“部分”列:

def allocation(df, ratio, part):
    k = df[part].max()
    frac, results = np.array(np.modf(k * df[ratio]))
    remainder = int(k - results.sum())
    indices = np.argsort(frac)[::-1]
    results[indices[0:remainder]] += 1
    return results.astype(int)

请注意,我的函数与我在顶部提到的问题中显示的函数之间的区别在于,我的函数返回整个组的值数组而不是单个值。我尝试了以下方法:

data.groupby('Group', group_keys=False).apply(allocation, ratio='Ratio', part='Part')
Out[67]: 
Group
A    [6, 2, 1, 1]
B    [9, 9, 1, 1]
dtype: object

这些数字是正确的。但是,我需要输出是一个可以分配回原始数据帧的系列,这样它看起来像这样:

    Group  Value  Part    Ratio     Allocate
0     A    6373    10    0.637300     6
1     A    2512    10    0.251200     2
2     A    603     10    0.060300     1
3     A    512     10    0.051200     1
4     B    5200    20    0.472727     9
5     B    4800    20    0.436364     9
6     B    501     20    0.045545     1
7     B    499     20    0.045364     1

我该怎么做呢?是否使用了正确的方法?

【问题讨论】:

【参考方案1】:

通常在使用apply带自定义功能时出现,我们可以使用concatenate修复它

s=df.groupby('Group', group_keys=False).apply(allocation, ratio='Ratio', part='Part').values
df['Allocate']=np.concatenate(s)
df
Out[71]: 
  Group  Value  Part     Ratio  Allocate
0     A   6373    10  0.637300         6
1     A   2512    10  0.251200         2
2     A    603    10  0.060300         1
3     A    512    10  0.051200         1
4     B   5200    20  0.472727         9
5     B   4800    20  0.436364         9
6     B    501    20  0.045545         1
7     B    499    20  0.045364         1

【讨论】:

这种方式并不总是正确的。由于结果s 将按组键排序,这可能与它们在原始帧df 中出现的顺序不同。要看到这一点,请尝试使用df2 = pd.concat([df[4:], df[:4]]) 构建另一个框架,然后执行与您相同的操作。你会得到一个错误的答案。【参考方案2】:

要以 pandas 方式进行,您可以让分配函数返回 DataFrameSeries

def allocation(df, ratio, part):
    k = df[part].max()
    frac, results = np.array(np.modf(k * df[ratio]))
    remainder = int(k - results.sum())
    indices = np.argsort(frac)[::-1]
    results[indices[0:remainder]] += 1
    df['Allocate'] = results.astype(int)
    return df

那么groupby.apply会直接给你想要的

In [61]: df.groupby('Group', group_keys=False).apply(allocation, ratio='Ratio', part='Part')
Out[61]:
  Group  Value  Part   Ratio  Allocate
0     A   6373    10  0.6373         6
1     A   2512    10  0.2512         2
2     A    603    10  0.0603         1
3     A    512    10  0.0512         1
4     B   5200    20  0.4727         9
5     B   4800    20  0.4364         9
6     B    501    20  0.0455         1
7     B    499    20  0.0454         1

即使原始数据帧未按Group 排序,这也有效。 试试df2 = pd.concat([df.iloc[:2], df.iloc[6:], df.iloc[2:6]])

【讨论】:

以上是关于使用多列的 Pandas groupby 函数的主要内容,如果未能解决你的问题,请参考以下文章

在 Pandas 中使用 Keras StandardScaler 和 Groupby 函数

Pandas 一次缩放多列并使用 groupby() 进行逆变换

一次在多列上使用 pandas groupby().apply(list) [重复]

Python Pandas groupby 并沿多列排序

Pandas Groupby 独特的多列

t 测试 groupby pandas 之后的多列