我想为每个ID
获得一定数量的列,但我不能使用例如。sample(n=30),因为我会得到一个ValueError,说明Cannot take a larger sample than population when 'replace=False'
.
我知道如果我把replace
变成True
,我就不会得到错误,但我不想那样。相反,对于那些没有30行的IDs
,我想取那些存在的,而不是更多。
我正在做什么:df = df.groupby('ID').sample(n=30)
我也尝试了df = df.groupby('ID').head(30)
,这得到了每个ID的前30行,只有那些没有超过30行的行可用。但它只取前30个,并不是随机抽取的。因此,它不适合我的情况。
我试过.frac
,但这并没有给我想要的结果。
在pandas df中还有其他方法吗?
谢谢你的帮助。
如果你不想做frac(1)
会做的全局洗牌,你可以只使用大小代替,如果它小于30
。为了避免创建另一个'ID'
列的问题,你可以稍微调整groupby
的设置。
创建一个新的Test-DataFrame
In [30]: df = pd.util.testing.makeDataFrame()
In [31]: df['ID'] = list(range(3))*6+[1,2]*6
In [40]: df['ID'].value_counts()
Out[40]:
1 12
2 12
0 6
Name: ID, dtype: int64
...:
然后你可以使用apply
来决定每组你需要多少个样本
In [32]: df2 = df.groupby('ID', as_index=False, group_keys=False).apply(lambda x: x.sample(min(8, len(x))))
Out[32]:
A B C D ID
20uv3SF4qh 0.8606 -0.8545 -0.2261 -0.2144 0
vBOWE8VPBL 0.9171 0.4375 0.9970 -0.9345 0
Kwzs4p5QYj -0.6896 -1.0051 0.9544 1.4635 0
XVfyETNO3g 0.4095 -1.2128 -1.5254 0.2521 0
l9zEX7eRM1 -0.4871 0.5637 0.9734 1.9705 0
... ... ... ... ... ..
lk3ldIhrpr -0.1244 -1.0035 -0.3616 -0.5537 2
NASmNcsBH9 -1.4542 0.6159 1.1075 0.7623 2
nN7CEiMFbc -0.6539 1.2619 1.2009 -0.2582 2
Z6gqbZY5PK 0.1713 0.0299 0.4418 -0.6228 2
KgyzhcYa4w 0.7239 0.2294 1.4657 -0.2369 2
In [38]: df2['ID'].value_counts()
Out[38]:
1 8
2 8
0 6
Name: ID, dtype: int64