【发布时间】:2014-04-23 17:04:54
【问题描述】:
假设我有一个看起来像这样的数据框:
Name Group_Id
AAA 1
ABC 1
CCC 2
XYZ 2
DEF 3
YYH 3
如何为每个Group_Id 随机选择一个(或多个)行?假设我想要每个Group_Id 随机抽奖,我会得到:
Name Group_Id
AAA 1
XYZ 2
DEF 3
【问题讨论】:
假设我有一个看起来像这样的数据框:
Name Group_Id
AAA 1
ABC 1
CCC 2
XYZ 2
DEF 3
YYH 3
如何为每个Group_Id 随机选择一个(或多个)行?假设我想要每个Group_Id 随机抽奖,我会得到:
Name Group_Id
AAA 1
XYZ 2
DEF 3
【问题讨论】:
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)
【讨论】:
从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
【讨论】:
df.groupby('Group_Id').apply(pd.DataFrame.sample, n=1).reset_index(drop=True)
有两种方法可以非常简单地做到这一点,一种除了基本的 pandas 语法外不使用任何东西:
df[['x','y']].groupby('x').agg(pd.DataFrame.sample)
对于 50k 行数据集,这需要 14.4 毫秒。
另一种稍快的方法涉及 numpy。
df[['x','y']].groupby('x').agg(np.random.choice)
对于(相同的)50k 行数据集,这需要 10.9 毫秒。
一般来说,在使用 pandas 时,最好坚持使用其原生语法。特别是对于初学者。
【讨论】:
n 项目? :-)
agg 对我不起作用,但 apply 对我有用。它还可以接受函数的参数:df[['x','y']].groupby('x').apply(pd.DataFrame.sample, n=n, replace=False)。请参阅文档pandas.pydata.org/pandas-docs/stable/reference/api/…
在优雅的单行中使用 groupby 和 random.choice:
df.groupby('Group_Id').apply(lambda x :x.iloc[random.choice(range(0,len(x)))])
【讨论】:
random.choice(range(0,len(x))) 最好写成np.random.randint(0, len(x))
df.sample(frac = 1.0).groupby('Group_Id').head(1) 快得多
对于每组随机选择一行,请尝试df.sample(frac = 1.0).groupby('Group_Id').head(1)
【讨论】:
如果一个组的样本少于所需的样本大小n,则提供的解决方案将失败。这解决了这个问题:
n = 10
df.groupby('Group_Id').apply(lambda x: x.sample(min(n,len(x)))).reset_index(drop=True)
【讨论】:
df.groupby('Group_Id').sample(n=1)
1.1.0 版中的新功能。 https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.core.groupby.DataFrameGroupBy.sample.html
【讨论】:
一种非常熊猫式的方式:
takesamp = lambda d: d.sample(n)
df = df.groupby('Group_Id').apply(takesamp)
【讨论】:
使用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)Return a random element from the non-empty sequence seq. If seq is empty, raises IndexError.
【讨论】:
您可以使用pandas.groupby、pandas.concat 和random.sample 的组合:
import pandas as pd
import random
df = pd.DataFrame({
'Name': ['AAA', 'ABC', 'CCC', 'XYZ', 'DEF', 'YYH'],
'Group_ID': [1,1,2,2,3,3]
})
grouped = df.groupby('Group_ID')
df_sampled = pd.concat([d.ix[random.sample(d.index, 1)] for _, d in grouped]).reset_index(drop=True)
print df_sampled
输出:
Group_ID Name
0 1 AAA
1 2 XYZ
2 3 DEF
【讨论】:
我又找到了一个:
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))])]
【讨论】: