【问题标题】:Stratified Sampling in PandasPandas 中的分层抽样
【发布时间】:2017-10-22 04:56:09
【问题描述】:

我查看了Sklearn stratified sampling docs 以及pandas docs 以及Stratified samples from Pandassklearn stratified sampling based on a column,但它们没有解决这个问题。

我正在寻找一种快速的 pandas/sklearn/numpy 方法来从数据集中生成大小为 n 的分层样本。但是,对于小于指定采样数的行,它应该取所有条目。

具体例子:

谢谢! :)

【问题讨论】:

标签: python pandas numpy scikit-learn


【解决方案1】:

将数字传递给采样时使用min。考虑数据框df

df = pd.DataFrame(dict(
        A=[1, 1, 1, 2, 2, 2, 2, 3, 4, 4],
        B=range(10)
    ))

df.groupby('A', group_keys=False).apply(lambda x: x.sample(min(len(x), 2)))

   A  B
1  1  1
2  1  2
3  2  3
6  2  6
7  3  7
9  4  9
8  4  8

【讨论】:

  • @piRSquared,假设我有一个 1M 行的 df,我想对其采样 10k,每个 user_id 至少有 10 个样本,你会如何处理它?
  • @whitfa 仍然对我有用,并且链接的更改根本不应该影响它。你用的是什么版本的熊猫?我正在使用0.25
  • 道歉@piRSquared,看来我弄错了!我会删除我原来的评论。
  • 当我的分组列具有高基数时,此解决方案非常慢。我想这是有道理的。无论如何,您能想出一种在这种情况下加快速度的方法吗?
【解决方案2】:

扩展groupby 答案,我们可以确保样本是平衡的。为此,当所有类的样本数 >= n_samples 时,我们可以为所有类取 n_samples(上一个答案)。当少数类包含n_samples时,我们可以取所有类的样本数与少数类相同。

def stratified_sample_df(df, col, n_samples):
    n = min(n_samples, df[col].value_counts().min())
    df_ = df.groupby(col).apply(lambda x: x.sample(n))
    df_.index = df_.index.droplevel(0)
    return df_

【讨论】:

  • 解释,发布的代码的作用以及它如何解决问题中的问题,很少不能改善答案。
【解决方案3】:

下面的样本一共N行,其中每组按其原始比例出现最接近的整数,然后shuffle并重置索引 使用:

df = pd.DataFrame(dict(
    A=[1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4],
    B=range(20)
))

又短又甜:

df.sample(n=N, weights='A', random_state=1).reset_index(drop=True)

加长版

df.groupby('A', group_keys=False).apply(lambda x: x.sample(int(np.rint(N*len(x)/len(df))))).sample(frac=1).reset_index(drop=True)

【讨论】:

  • 短版本有一个问题,它没有保持原始比例:使用参数 weights = category 列实际上没有意义,例如它可以是一个字符串。如果您真的想使用 df.sample,则需要计算一个附加列,该列等于类别列的频率。但长版本有效!
  • 短版本不适用于二进制数据,例如df = pd.DataFrame({'A': [np.random.randint(0, 2) for _ in range(100)]})
  • 如果列 A 不是数字,则将不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 2017-10-31
相关资源
最近更新 更多