按列对分组数据帧进行采样

Posted

技术标签:

【中文标题】按列对分组数据帧进行采样【英文标题】:Sampling a grouped dataframe by column 【发布时间】:2017-08-20 17:28:35 【问题描述】:

我有一个数据框,我将其分组如下并将某些操作应用于特定列:

 df = df.groupby(['A', 'B', 'C']).agg('ID': 'count', 'AMT': 'sum')

对于每个 groupby 组合 (~15) 我想随机抽样属于每个组合的行并返回一个样本 ID 并在第三个输出列中报告它。或者我真的只是希望该组合中的行中的一个 ID 出现在表中,我不在乎它是否“随机”。

我尝试了以下方法:

 df = df.groupby(['A', 'B', 'C']).agg('ID': 'count', 'AMT': 'sum', 'ID': 'sample')

并收到错误:

 AttributeError: Cannot access callable attribute 'sample' of 'SeriesGroupBy' objects, try using the 'apply' method

于是我尝试了:

 func = lambda x: x.sample
 df = df.groupby(['A', 'B', 'C']).agg('ID': 'count', 'AMT': 'sum', 'ID': apply(func))

没用所以我试了

df = df.groupby(['A', 'B', 'C']).agg('ID': 'count', 'AMT': 'sum', 'ID': lambda x: x.sample)   

这也不起作用。我查看了以下相关问题的链接,但它们似乎也没有帮助我。

Select multiple groups from pandas groupby object

http://pandas.pydata.org/pandas-docs/stable/groupby.html

Get specific element from Groups after applying groupby - PANDAS

How to access pandas groupby dataframe by key

https://chrisalbon.com/python/pandas_apply_operations_to_dataframes.html

关于如何处理的任何想法?

【问题讨论】:

【参考方案1】:

鉴于您使用agg 进行聚合,您必须返回单个元素。所以你可以尝试使用

'ID': lambda x: x.sample.tolist()

【讨论】:

【参考方案2】:

您尝试使用的代码存在一些问题。

lambda x: x.sample 返回 函数 本身而不是调用它(执行 lambda x: x.sample())。 x.sample() 返回一个 Series 对象。 .agg() 排除单个标量值或列表,因此会导致异常。你可以做x.sample().tolist(),但现在你有一个列表而不是单个值。在这里使用numpy.random.choice() 更方便。 在传递给.agg() 的字典中多次指定同一列不起作用。只有最后一个会坚持。将您要用作列表或字典的函数分配给该列。

考虑到上述情况,您将得到以下解决方案:

import numpy as np
df = df.groupby(['A', 'B', 'C']).agg('ID': ('count', np.random.choice), 'AMT': 'sum')

【讨论】:

【参考方案3】:

考虑示例数据框df

np.random.seed([3,1415])
df = pd.DataFrame(dict(
        A=list('x'*8 + 'y'*8 + 'z'*8) * 2,
        B=list('x'*4 + 'y'*4 + 'z'*4) * 4,
        C=list('x'*2 + 'y'*2 + 'z'*2) * 8,
        ID=range(48),
        AMT=np.random.rand(48)
    ))

print(df)

    A       AMT  B  C  ID
0   x  0.444939  x  x   0
1   x  0.407554  x  x   1
2   x  0.460148  x  y   2
3   x  0.465239  x  y   3
4   x  0.462691  y  z   4
5   x  0.016545  y  z   5
6   x  0.850445  y  x   6
7   x  0.817744  y  x   7
8   y  0.777962  z  y   8
9   y  0.757983  z  y   9
...
39  y  0.778883  x  y  39
40  z  0.651676  y  z  40
41  z  0.136097  y  z  41
42  z  0.544838  y  x  42
43  z  0.035073  y  x  43
44  z  0.275079  z  y  44
45  z  0.706685  z  y  45
46  z  0.713614  z  z  46
47  z  0.776050  z  z  47

解决方案#1

您可以使用np.random.choice 选择一个

f = dict(
    ID=dict(Count='count', Sample=np.random.choice),
    AMT=dict(Sum='sum', Max='max', Min='min')
)

df.groupby(['A', 'B', 'C']).agg(f)

            AMT                         ID      
            Sum       Max       Min Sample Count
A B C                                           
x x x  2.458188  0.866059  0.407554     25     4
    y  1.993843  0.691271  0.377185     27     4
  y x  3.070036  0.850445  0.700900      7     4
    z  1.139663  0.462691  0.016545     28     4
y x x  2.824838  0.926879  0.253200     13     4
    y  2.166114  0.778883  0.117642     39     4
  z y  2.351120  0.796487  0.018688      8     4
    z  3.367248  0.934829  0.700566     10     4
z y x  1.118176  0.544838  0.035073     19     4
    z  1.133523  0.651676  0.136097     16     4
  z y  1.870361  0.706685  0.275079     44     4
    z  2.412484  0.836997  0.085823     47     4

解决方案#2

挑选1个以上

您可以使用pd.DataFrame.sample 获取df 的整片

df.groupby(['A', 'B', 'C']).apply(pd.DataFrame.sample, n=2)

          A       AMT  B  C  ID
A B C                          
x x x 25  x  0.866059  x  x  25
      0   x  0.444939  x  x   0
    y 26  x  0.691271  x  y  26
      27  x  0.377185  x  y  27
  y x 6   x  0.850445  y  x   6
      31  x  0.700946  y  x  31
    z 28  x  0.225146  y  z  28
      29  x  0.435280  y  z  29
y x x 13  y  0.926879  x  x  13
      37  y  0.253200  x  x  37
    y 38  y  0.548054  x  y  38
      39  y  0.778883  x  y  39
  z y 33  y  0.018688  z  y  33
      32  y  0.796487  z  y  32
    z 11  y  0.831104  z  z  11
      10  y  0.934829  z  z  10
z y x 42  z  0.544838  y  x  42
      43  z  0.035073  y  x  43
    z 41  z  0.136097  y  z  41
      17  z  0.199844  y  z  17
  z y 20  z  0.278735  z  y  20
      45  z  0.706685  z  y  45
    z 22  z  0.085823  z  z  22
      47  z  0.776050  z  z  47

【讨论】:

以上是关于按列对分组数据帧进行采样的主要内容,如果未能解决你的问题,请参考以下文章

如何按列对数据框进行分组?

php 按列对SQL结果进行分组

如何按列对pyspark中的数据框进行分组并以该列作为键并以记录列表作为其值来获取字典?

合并数据框时按列分组

熊猫数据框按列位置分组

熊猫数据框分组和求和,组内,跨行值而不是按列