基于列值的组比和随机抽样。

问题描述 投票:0回答:1

我有一个数据框,我想按以下方式进行分组。grp1, grp2 列,然后从每组中随机抽取样本,根据列的 how_many.

这是我的样本数据

   grp1  grp2  how_many    val
0     a     1         2  2993
1     a     1         2  8244
2     a     2         1  7148
3     a     1         2  5326
4     a     3         2  5577
5     a     3         2  5651
6     a     1         2  6297
7     a     2         1  2657
8     a     2         1  9774
9     a     1         2  4075
10    a     3         2  6780
11    b     1         1  1765
12    b     1         1  5592
13    b     1         1  9936
14    b     2         4  4324
15    b     2         4  6823
16    b     2         4  9184
17    b     2         4  7498
18    b     2         4  3810

这是预期的结果(当然是随机的)。

  grp1  grp2  how_many    val
0    a     1         2  2993
1    a     1         2  5326
2    a     2         1  9774
3    a     3         2  6780
4    a     3         2  5651
5    b     1         1  5592
6    b     2         4  6823
7    b     2         4  9184
8    b     2         4  7498
9    b     2         4  3810

我的方法是按照 本说明然而,在我的案例中,我没有一个稳定的样本量,它根据列值而变化。

我也尝试使用 multi_index 组比列上,但得到一个错误,说 MemoryError: Unable to allocate 107. GiB for an array with shape (57244869081,) and data type int16. 这只是我的数据的一个小样本。

希望得到任何帮助

python pandas pandas-groupby
1个回答
3
投票

如果列中的值相同,这两种解决方案都可以工作 how_many 每组。

创建lambda函数 DataFrame.sample 并按组调用。

df1= (df.groupby(['grp1','grp2'])
        .apply(lambda x: x.sample(x['how_many'].iat[0]))
        .reset_index(drop=True))
print (df1)
  grp1  grp2  how_many   val
0    a     1         2  2993
1    a     1         2  6297
2    a     2         1  9774
3    a     3         2  5651
4    a     3         2  5577
5    b     1         1  1765
6    b     2         4  6823
7    b     2         4  4324
8    b     2         4  7498
9    b     2         4  9184

为了提高性能,我们的解决方案是开箱即用

首先创建随机的所有行通过 frac=1DataFrame.sample,然后通过以下方式创建计数器 GroupBy.cumcount 较量 Series.le 对于 <=如果需要的话,最后按组进行排序。

df1 = df.sample(frac=1)
df1 = df1[df1.groupby(['grp1','grp2']).cumcount().add(1).le(df1['how_many'])]
df1 = df1.sort_values(['grp1','grp2'])
print (df1)
   grp1  grp2  how_many   val
0     a     1         2  2993
1     a     1         2  8244
2     a     2         1  7148
5     a     3         2  5651
4     a     3         2  5577
13    b     1         1  9936
16    b     2         4  9184
17    b     2         4  7498
15    b     2         4  6823
14    b     2         4  4324

详情:

首先是随机改变列的顺序。

df1 = df.sample(frac=1)
print (df1)
   grp1  grp2  how_many   val
15    b     2         4  6823
18    b     2         4  3810
10    a     3         2  6780
11    b     1         1  1765
14    b     2         4  4324
2     a     2         1  7148
16    b     2         4  9184
7     a     2         1  2657
9     a     1         2  4075
1     a     1         2  8244
13    b     1         1  9936
17    b     2         4  7498
8     a     2         1  9774
4     a     3         2  5577
12    b     1         1  5592
0     a     1         2  2993
5     a     3         2  5651
6     a     1         2  6297
3     a     1         2  5326

然后按组建立计数器,并通过掩码过滤--按列比较。how_many 是返回第一行,但由于randoch改变了顺序,所以返回的是随机行。

print (df1.assign(counter=df1.groupby(['grp1','grp2']).cumcount().add(1), 
                  mask=df1.groupby(['grp1','grp2']).cumcount().add(1).le(df1['how_many'])))
   grp1  grp2  how_many   val  counter   mask
15    b     2         4  6823        1   True
18    b     2         4  3810        2   True
10    a     3         2  6780        1   True
11    b     1         1  1765        1   True
14    b     2         4  4324        3   True
2     a     2         1  7148        1   True
16    b     2         4  9184        4   True
7     a     2         1  2657        2  False
9     a     1         2  4075        1   True
1     a     1         2  8244        2   True
13    b     1         1  9936        2  False
17    b     2         4  7498        5  False
8     a     2         1  9774        3  False
4     a     3         2  5577        2   True
12    b     1         1  5592        3  False
0     a     1         2  2993        3  False
5     a     3         2  5651        3  False
6     a     1         2  6297        4  False
3     a     1         2  5326        5  False

筛选:

df1 = df1[df1.groupby(['grp1','grp2']).cumcount().add(1).le(df1['how_many'])]
print (df1)
   grp1  grp2  how_many   val
15    b     2         4  6823
18    b     2         4  3810
10    a     3         2  6780
11    b     1         1  1765
14    b     2         4  4324
2     a     2         1  7148
16    b     2         4  9184
9     a     1         2  4075
1     a     1         2  8244
4     a     3         2  5577

如果需要的话,进行排序。

df1 = df1.sort_values(['grp1','grp2'])
print (df1)
   grp1  grp2  how_many   val
9     a     1         2  4075
1     a     1         2  8244
2     a     2         1  7148
10    a     3         2  6780
4     a     3         2  5577
11    b     1         1  1765
15    b     2         4  6823
18    b     2         4  3810
14    b     2         4  4324
16    b     2         4  9184
© www.soinside.com 2019 - 2024. All rights reserved.