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

时间:2017-03-27 20:36:54

标签: python python-2.7 pandas

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

 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

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

3 个答案:

答案 0 :(得分:2)

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

  • lambda x: x.sample会返回函数而不是调用它(do 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'})

答案 1 :(得分:2)

考虑示例数据框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

答案 2 :(得分:0)

如果使用agg进行聚合,则必须返回单个元素。所以你可以尝试使用

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