我有一个数据框,我想按以下方式进行分组。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
. 这只是我的数据的一个小样本。
希望得到任何帮助
如果列中的值相同,这两种解决方案都可以工作 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=1
在 DataFrame.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