【问题标题】:Pandas Random Weighted ChoicePandas 随机加权选择
【发布时间】:2017-12-26 16:07:27
【问题描述】:

我想使用Pandas 随机选择一个考虑权重的值。

df:

   0  1  2  3  4  5
0  40  5 20 10 35 25
1  24  3 12  6 21 15
2  72  9 36 18 63 45
3  8   1  4  2  7 5
4  16  2  8  4 14 10
5  48  6 24 12 42 30

我知道使用np.random.choice,例如:

x = np.random.choice(
  ['0-0','0-1',etc.], 
  1,
  p=[0.4,0.24 etc.]
)

因此,我想从df 以与np.random.choice 类似的样式/替代方法获得输出,但使用Pandas。与我上面所做的手动插入值相比,我想以更有效的方式这样做。

使用np.random.choice 我知道所有值加起来必须等于1。我不确定如何解决这个问题,也不确定如何使用Pandas 根据权重随机选择一个值。

当引用一个输出时,如果随机选择的权重例如是 40,那么输出将是 0-0,因为它位于 column 0row 0 等等。

【问题讨论】:

    标签: python python-2.7 pandas numpy


    【解决方案1】:

    堆栈数据帧:

    stacked = df.stack()
    

    将权重归一化(使它们加起来为 1):

    weights = stacked / stacked.sum()
    # As GeoMatt22 pointed out, this part is not necessary. See the other comment.
    

    然后使用示例:

    stacked.sample(1, weights=weights)
    Out: 
    1  2    12
    dtype: int64
    
    # Or without normalization, stacked.sample(1, weights=stacked)
    

    DataFrame.sample 方法允许您从行或列中采样。考虑一下:

    df.sample(1, weights=[0.4, 0.3, 0.1, 0.1, 0.05, 0.05])
    Out: 
        0  1   2  3   4   5
    1  24  3  12  6  21  15
    

    它选择一行(第一行有 40% 的机会,第二行有 30% 的机会等)

    这也是可能的:

    df.sample(1, weights=[0.4, 0.3, 0.1, 0.1, 0.05, 0.05], axis=1)
    Out: 
       1
    0  5
    1  3
    2  9
    3  1
    4  2
    5  6
    

    相同的过程,但 40% 的机会与第一列相关联,我们正在从列中进行选择。但是,您的问题似乎暗示您不想选择行或列 - 您想选择里面的单元格。因此,我将维度从 2D 更改为 1D。

    df.stack()
    
    Out: 
    0  0    40
       1     5
       2    20
       3    10
       4    35
       5    25
    1  0    24
       1     3
       2    12
       3     6
       4    21
       5    15
    2  0    72
       1     9
       2    36
       3    18
       4    63
       5    45
    3  0     8
       1     1
       2     4
       3     2
       4     7
       5     5
    4  0    16
       1     2
       2     8
       3     4
       4    14
       5    10
    5  0    48
       1     6
       2    24
       3    12
       4    42
       5    30
    dtype: int64
    

    因此,如果我现在从中采样,我将同时采样一行和一列。例如:

    df.stack().sample()
    Out: 
    1  0    24
    dtype: int64
    

    选择第 1 行和第 0 列。

    【讨论】:

    • 太棒了!谢谢。所以这与np.random.choice 的风格相似吗?另外,在这种情况下stacking 的目的是什么?
    • @LearningToPython 是的,它的工作原理与 random.choice 完全一样。堆叠的目的是拥有一个一维对象(因为 pandas sample 允许您从轴 0 或轴 1 采样(从行或列 - 据我所知,不是同时)。
    • 好的。万分感谢。 1 最后一个问题(对不起) - 那么为什么在这种情况下需要堆叠?
    • np.random.choice 不同,pd.DataFrame.sample 的权重不需要归一化(只是非负数)。
    • @LearningToPython 我编辑了帖子来解释那部分。
    猜你喜欢
    • 2015-07-05
    • 2010-09-08
    • 2020-05-25
    • 1970-01-01
    • 2023-03-31
    • 2020-01-22
    • 1970-01-01
    相关资源
    最近更新 更多