Python:每个组的随机选择
假设我有一个数据帧,看起来像:Python:每个组的随机选择,python,random,pandas,Python,Random,Pandas,假设我有一个数据帧,看起来像: Name Group_Id AAA 1 ABC 1 CCC 2 XYZ 2 DEF 3 YYH 3 如何为每个组Id随机选择一行(或多行)?假设我希望每个组Id随机抽取一次,我会得到: Name Group_Id AAA 1 XYZ 2 DEF 3 使用random.choice,您可以执行以下操作: import random name_group = {'AAA': 1, 'ABC':1, 'CCC':2, 'XYZ':2, 'DEF'
Name Group_Id
AAA 1
ABC 1
CCC 2
XYZ 2
DEF 3
YYH 3
如何为每个组Id
随机选择一行(或多行)?假设我希望每个组Id
随机抽取一次,我会得到:
Name Group_Id
AAA 1
XYZ 2
DEF 3
使用
random.choice
,您可以执行以下操作:
import random
name_group = {'AAA': 1, 'ABC':1, 'CCC':2, 'XYZ':2, 'DEF':3, 'YYH':3}
names = [name for name in name_group.iterkeys()] #create a list out of the keys in the name_group dict
first_name = random.choice(names)
first_group = name_group[first_name]
print first_name, first_group
random.choice(seq)
您可以使用、和的组合: 输出:
Group_ID Name
0 1 AAA
1 2 XYZ
2 3 DEF
在优雅的一行中使用groupby和random.choice:
df.groupby('Group_Id').apply(lambda x :x.iloc[random.choice(range(0,len(x)))])
From
0.16.x
提供了一种从对象轴返回项目随机样本的方法
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
对于每个组只随机选择一行,请尝试
df.sample(frac=1.0).groupby('group_Id').head(1)
有两种方法可以非常简单地做到这一点,一种方法不使用任何基本语法:
df[['x','y']].groupby('x').agg(pd.DataFrame.sample)
对于50k行数据集,这需要14.4ms
另一个稍微快一点的方法是numpy
df[['x','y']].groupby('x').agg(np.random.choice)
对于(相同的)50k行数据集,这需要10.9ms的时间
一般来说,在使用pandas时,最好坚持其本机语法。特别是初学者 一种非常奇怪的方式:
takesamp = lambda d: d.sample(n)
df = df.groupby('Group_Id').apply(takesamp)
如果一个组的样本少于所需的样本量
n
,则提供的解决方案将失败。这解决了这个问题:
n = 10
df.groupby('Group_Id').apply(lambda x: x.sample(min(n,len(x)))).reset_index(drop=True)
我找到了另一个:
size=2
count_s = df['Id'].value_counts()
df.iloc[np.concatenate([previous_count + np.random.choice(count, size)
for count, previous_count in zip(count_s,
count_s.shift(fill_value=0))])]
版本1.1.0中的新功能。
set replace=False,如果不希望每个组两次获得相同的行。如果使用时间戳列创建基于频率的pd.Grouper(),则建议的方法将生成两个同名的时间戳索引列。不太理想的情况。下面我发布了一个更简单(代码更少,更容易记住,一般来说复杂性更低)的方法来做同样的事情。
random.choice(range(0,len(x))
最好写为np.random.randint(0,len(x))
有些人可能稍微倾向于使用numpy.random.choice,这允许您指定a)要从总体中采集的样本数量和b)是否需要替换<代码>df.sample(frac=1.0)。groupby('Group_Id')。头(1)太多了faster@ihadanny”的建议更为“泛泛”,也可推广到n>1,尽管这是最泛泛的答案,但它如何可能推广到每组抽样n
项目?:-)@matansteragg
对我不起作用,但apply
起作用。它还可以接受函数的参数:df[['x','y']].groupby('x').apply(pd.DataFrame.sample,n=n,replace=False)
。请参见文档。此方法将从每个组的每个列中进行不同的随机选择,而不是选择每个组中的整行。来自@ihadanny的答案将选择整行,而且速度更快。或者:df.groupby('Group\u Id')。apply(pd.DataFrame.sample,n=1)。reset\u index(drop=True)
这是最快的答案,可用于选择跨多列的行。
takesamp = lambda d: d.sample(n)
df = df.groupby('Group_Id').apply(takesamp)
n = 10
df.groupby('Group_Id').apply(lambda x: x.sample(min(n,len(x)))).reset_index(drop=True)
size=2
count_s = df['Id'].value_counts()
df.iloc[np.concatenate([previous_count + np.random.choice(count, size)
for count, previous_count in zip(count_s,
count_s.shift(fill_value=0))])]
df.groupby('Group_Id').sample(n=1)