【问题标题】:Random selection of a row from a pandas DataFrame with weights从带有权重的 pandas DataFrame 中随机选择一行
【发布时间】:2020-07-21 22:24:20
【问题描述】:

我正在尝试根据提供的权重从 pandas DataFrame 中随机选择一行。我尝试对这些参数使用 .sample() 方法,但无法使语法正常工作:

import pandas as pd

df = pd.DataFrame({
    'label': [1,0,1,-1],
    'ind': [2,3,6,8],
})

df.sample(n=1, weights=[0.5, 0.4, 0.1], axis=0)

标签是 1,0 和 -1,我想为每个标签分配不同的权重以进行随机选择。

【问题讨论】:

  • 澄清一下:对于这个例子,你希望函数例如。返回“标签”为 1 50% 的行?
  • 没错!它应该在 50% 的时间内返回带有标签 1 的行。
  • 我不希望它基于 DataFrame 中的计数,而是预定义的权重。
  • 您的权重列表比 df 中的列短。放大后就可以了。

标签: python python-3.x pandas


【解决方案1】:

您应该调整权重,使其与预期分布相匹配:

weights = {-1:0.1, 0:0.4, 1:0.5}

scaled_weights = (pd.Series(weights) / df.label.value_counts(normalize=True))

df.sample(n=1, weights=df.label.map(scaled_weights) )

10000 个样本的测试分布

(df.sample(n=10000, replace=True, random_state=1,
           weights=df.label.map(scaled_weights))
   .label.value_counts(normalize=True)
)

输出:

 1    0.5060
 0    0.3979
-1    0.0961
Name: label, dtype: float64

【讨论】:

  • 非常感谢!称重至关重要,而我完全错过了那部分。
【解决方案2】:

对于每一行,将所需的权重除以该标签在 df 中的频率:

weights=df['label'].replace({1:0.5,0:0.4,-1:0.1})/df.groupby('label')['label'].transform('count')

df.sample(n=1, weights=weights, axis=0)

【讨论】:

    【解决方案3】:

    您可以尝试以下代码。它将字典中的所需权重分配给 df 中的行(假设您按这样的顺序给它们)。如果您希望权重取决于元素的数量 - 您可以将 lambda 替换为更复杂的函数。

    w = df['label'].apply( lambda x: {-1:0.5, 0:0.4, 1:0.1}[x] )
    df.sample(n=1, weights=w, axis=0)
    

    【讨论】:

    • 不幸的是,这不符合要求。它传递的权重是 [0.5, 0.4, 0.5, 0.1] 所以它会在三分之二的时间内返回标签为 1 的元素。
    • 这不会提供所需的分布[0.5,0.4,0.1]
    猜你喜欢
    • 2021-01-04
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 2012-05-20
    • 2019-08-19
    • 2013-05-23
    • 2014-04-27
    • 1970-01-01
    相关资源
    最近更新 更多