Python:每组随机选择

Plu*_*ug4 32 python random pandas

假设我有一个类似于的数据框:

Name Group_Id
AAA  1
ABC  1
CCC  2
XYZ  2
DEF  3 
YYH  3
Run Code Online (Sandbox Code Playgroud)

我怎样才能为每个行随机选择一行(或多行)Group_Id?假设我想要一个随机抽奖Group_Id,我会得到:

Name Group_Id
AAA  1
XYZ  2
DEF  3
Run Code Online (Sandbox Code Playgroud)

beh*_*uri 22

size = 2        # sample size
replace = True  # with replacement
fn = lambda obj: obj.loc[np.random.choice(obj.index, size, replace),:]
df.groupby('Group_Id', as_index=False).apply(fn)
Run Code Online (Sandbox Code Playgroud)

  • 如果您不想在每个组中两次获得相同的行,请设置 replace=False。 (3认同)

Zer*_*ero 19

0.16.x以后开始pd.DataFrame.sample提供了一种从对象轴返回项目的随机样本的方法.

In [664]: df.groupby('Group_Id').apply(lambda x: x.sample(1)).reset_index(drop=True)
Out[664]:
  Name  Group_Id
0  ABC         1
1  XYZ         2
2  DEF         3
Run Code Online (Sandbox Code Playgroud)

  • 或者:df.groupby('Group_Id')。apply(pd.DataFrame.sample,n = 1).reset_index(drop = True)` (2认同)

gra*_*per 10

在优雅的单行中使用groupby和random.choice:

df.groupby('Group_Id').apply(lambda x :x.iloc[random.choice(range(0,len(x)))])
Run Code Online (Sandbox Code Playgroud)

  • `random.choice(range(0,len(x)))`最好写成`np.random.randint(0,len(x))` (3认同)
  • `df.sample(frac = 1.0).groupby('Group_Id').head(1)`快得多 (3认同)

iha*_*nny 9

为每组随机选择一行尝试 df.sample(frac = 1.0).groupby('Group_Id').head(1)


mik*_*ila 9

有两种方法可以非常简单地完成此操作,一种不使用基本的pandas语法以外的任何方法:

df[['x','y']].groupby('x').agg(pd.DataFrame.sample)
Run Code Online (Sandbox Code Playgroud)

50k行数据集耗时14.4ms。

另一种更快的方法涉及numpy。

df[['x','y']].groupby('x').agg(np.random.choice)
Run Code Online (Sandbox Code Playgroud)

使用(相同)50k行数据集需要10.9毫秒。

一般来说,使用熊猫时,最好坚持使用其本机语法。特别是对于初学者。

  • 这是最泛泛的答案,但是如何将其推广到每个组中抽取n个项目呢?:-) (5认同)
  • @matanster `agg` 对我不起作用,但 `apply` 对我有用。它还可以接受函数的参数:`df[['x','y']].groupby('x').apply(pd.DataFrame.sample, n=n, Replace=False)`。请参阅文档https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.agg.html (3认同)

Hap*_*lop 9

如果一个组的样本少于所需的样本量,那么所提供的解决方案就会失败n。这解决了这个问题:

n = 10
df.groupby('Group_Id').apply(lambda x: x.sample(min(n,len(x)))).reset_index(drop=True)
Run Code Online (Sandbox Code Playgroud)