【问题标题】:Sample dataframe by value in column and keep all rows按列中的值对数据框进行采样并保留所有行
【发布时间】:2021-04-03 21:38:44
【问题描述】:

我想使用特定列中的值对 Pandas 数据框进行采样,但我想保留所有行的值都在样本中。

例如,在下面的数据框中,我想随机抽取b 中的部分值,但保留ac 中的所有 对应行。

d = pd.DataFrame({'a': range(1, 101, 1),'b': list(range(0, 100, 4))*4, 'c' :list(range(0, 100, 2))*2} )

来自 16% 样本的所需示例输出:

Out[66]: 
     a   b   c
0    1   0   0
1   26   0  50
2   51   0   0
3   76   0  50
4    4  12   6
5   29  12  56
6   54  12   6
7   79  12  56
8   18  68  34
9   43  68  84
10  68  68  34
11  93  68  84
12  19  72  36
13  44  72  86
14  69  72  36
15  94  72  86

我已尝试对系列进行采样并合并回主要数据,如下所示:

In [66]: pd.merge(d, d.b.sample(int(.16 * d.b.nunique())))

这会创建所需的输出,但似乎效率低下。我的真实数据集在b 中有数百万个值和数亿行。我知道我也可以使用一些版本的 ``isin```,但那也很慢。

有没有更有效的方法来做到这一点?

【问题讨论】:

  • 您是否尝试过为frac 参数传递一个值?也许实现比找到唯一值更快。 pandas.pydata.org/docs/reference/api/…
  • 你能分享你正在使用的数据吗(上传到谷歌驱动器或github)
  • 很遗憾,我无法分享这些数据,因为它们受到隐私法的保护。

标签: python pandas dataframe sample


【解决方案1】:

我真的怀疑isin 很慢:

uniques = df.b.unique()

# this maybe the bottle neck
samples = np.random.choice(uniques, replace=False, size=int(0.16*len(uniques)) )

# sampling here
df[df.b.isin(samples)]

您可以分析上述步骤。如果samples=...速度慢,可以试试:

idx = np.random.rand(len(uniques))
samples = uniques[idx<0.16]

这些在我的系统上花费了大约 100 毫秒的 1000 万行。

注意d.b.sample(int(.16 * d.b.nunique())) 不会对 b 中的唯一值进行抽样 0.16

【讨论】:

  • 谢谢,您能否解释一下您的注意,即 d.b.sample() 不会对 b 中的 0.16 个唯一值进行采样?这似乎适用于我的示例
  • @svenkatesh 代码会变成n=int(.16 * d.b.nunique()); d.b.sample(n)d.b.sample 不关心d.b 系列中的值,0.16 * d.b.nunique() 只是一个数字。因此,该命令只是从系列中随机抽样,而不关心唯一值。也就是说,如果您有 100 行和 b==10,则可能会选择其中的 16 行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-23
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多