【问题标题】:python dictionary, assign random values the sum of which is a certain valuepython字典,分配随机值,其总和为某个值
【发布时间】:2016-11-15 23:20:36
【问题描述】:

我正在制作一个python程序,其中随机值生成n次,用作模型模拟的参数值。

我有一个定义每个参数边界的字典,例如:

parameters = {'A': random.uniform(1,10), 'B': random.uniform(20,40)}

我想添加一些总和必须为 1 的参数,例如:

params = {'C1': random.uniform(0.0,1.0), 'C2': 1 - params['C1']}

后者显然无法生成KeyError: 'C1'

我也尝试过类似的方法:

params = {'A': random.uniform(1,10), 'B': random.uniform(20,40), 'C': {'C1': None,'C2': None}}

def class_fractions():
    for key in params['C']:
        if key == 'C1':
            params['C'][key] = random.uniform(0.0,1.0)
        if key == 'C2':
            params['C'][key] = 1.0 - params['C'][key]

但是在调用函数后我得到了 TypeError

TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'

有什么建议吗?

【问题讨论】:

  • 您的 for 循环将不起作用,因为 dict 不保证订单。所以C2可以在C1之前执行。
  • params['C']['C2'] 始终为 None。从未赋值。

标签: python dictionary random


【解决方案1】:

您的代码的问题是因为dict 在 Python 中没有排序。当你这样做时:

for key in params['C']

您获得C2 密钥的时间早于C1。实际上,您甚至不需要迭代 dict 只需在 dict 中设置值,例如:

def class_fractions():
    params['C']['C1'] = random.uniform(0.0,1.0)
    params['C']['C2'] = 1.0 - params['C']['C1']

你甚至不需要单独的函数,因为它只更新同一个字典,只需你这样做:

params = {'A': random.uniform(1,10), 'B': random.uniform(20,40)} # create partial dict
c_dict = {'C1': random.uniform(1,10)}  # create sub-dict to store random value
c_dict['C2'] = 1 - c_dict['C1']  # get value that you want
params['C'] = c_dict       # add entry into parent dict

【讨论】:

    【解决方案2】:

    从您对for 循环的使用看来,您可能真的有更多的参数,而不仅仅是两个。在这种情况下,您可以生成一个填充了随机数的值列表,然后然后将其缩放为总和为 1,as described in this other answer。然后遍历字典键和列表项的压缩视图,并将这些项分配给字典。

    或者,直接对字典进行操作:

    params = {k: random.uniform(0, 1) for k in ('C1', 'C2', 'C3')}
    total = sum(params.values())
    params = {k: (v / total) for k, v in params.items()}
    

    【讨论】:

      【解决方案3】:

      如果你真的不想使用你的class_fraction,并立即初始化参数,那么需要使用OrderDict:

      import random
      from collections import OrderedDict
      
      params = {'A': random.uniform(1,10), 'B': random.uniform(20,40), 'C':OrderedDict([('C1', None),('C2', None)])}
      
      
      def class_fractions():
          for key in params['C']:
              if key == 'C1':
                  params['C'][key] = random.uniform(0.0,1.0)
              if key == 'C2':
                  params['C'][key] = 1.0 - params['C']['C1']
      
      
      class_fractions()
      print(params)
      

      结果:

      {'B': 37.3088618142464, 'A': 2.274415152225316, 'C': OrderedDict([('C1', 0.12703200100786471), ('C2', 0.8729679989921353)])}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-14
        • 1970-01-01
        • 1970-01-01
        • 2012-07-26
        • 2010-11-06
        相关资源
        最近更新 更多