在dict上应用公式并生成结果

时间:2016-12-14 07:38:27

标签: python dictionary

我需要在现有的dict上应用一些公式,并使用新的键和计算值生成一个新的dict。

考虑下面的字典:

samples_dict = {'sample1': {u'Bhubaneswar': 21.0, u'Mumbai': 63.0},
               'sample2': {u'Bhubaneswar': 600.67, u'Mumbai': 1000.01},
               'sample3': {u'Bhubaneswar': 700.0, u'Mumbai': 2100.0},
               'sample4': {u'Bhubaneswar': 625.94, u'Mumbai': 1877.82},
           'sample5': {u'Bhubaneswar': 425.94, u'Mumbai': 877.82}}

这里我需要按如下方式应用公式:

formula = sample1+sample2

我正在创建一个包含键的列表,我需要使用公式在dict中检查。现在也将创建一个新的词典。

sample_list = re.findall("\w+,*", formula)

new_dict = {sample: samples_dict[sample] for sample in sample_list if sample in samples_dict}
我现在创建的

new_dict现在如下:

{'sample1': {u'Mumbai': 63.0, u'Bhubaneswar': 21.0}, 'sample2': {u'Mumbai': 1000.01, u'Bhubaneswar': 600.67}}

现在我需要将此公式应用于此dict,以使用给定的公式创建新项目。

最后我需要与基础字典合并,我现在需要结果如下:

我希望可以使用eval,有人帮我怎么做。

samples_dict = {'sample1': {u'Bhubaneswar': 21.0, u'Mumbai': 63.0},
               'sample2': {u'Bhubaneswar': 600.67, u'Mumbai': 1000.01},
               'sample3': {u'Bhubaneswar': 700.0, u'Mumbai': 2100.0},
               'sample4': {u'Bhubaneswar': 625.94, u'Mumbai': 1877.82},
           'sample5': {u'Bhubaneswar': 425.94, u'Mumbai': 877.82},
           'sample6': {u'Bhubaneswar': 621.67, u'Mumbai': 1063.01}}

有人帮助我。

3 个答案:

答案 0 :(得分:0)

我认为这就是你想要的。

import pprint


samples_dict = {
    'sample1': {u'Bhubaneswar': 21.0, u'Mumbai': 63.0},
    'sample2': {u'Bhubaneswar': 600.67, u'Mumbai': 1000.01},
    'sample3': {u'Bhubaneswar': 700.0, u'Mumbai': 2100.0},
    'sample4': {u'Bhubaneswar': 625.94, u'Mumbai': 1877.82},
    'sample5': {u'Bhubaneswar': 425.94, u'Mumbai': 877.82}
}


def formula(key1, key2, original_dict, new_name):
    temp_list = []
    original_dict[new_name] = {}

    for k, v in original_dict.items():
        if k == key1 or k == key2:
            temp_list.append(v)

    for k, v in temp_list[0].items():
        original_dict[new_name][k] = v + temp_list[1].get(k, 0)

    return original_dict


pprint.pprint(formula('sample1', 'sample2', samples_dict, 'sample6'))

答案 1 :(得分:0)

虽然你认为这很简单,但这是一个相当复杂的问题,真正需要拆分的是较小的部分。

假设:

  • 输入词典是dicts的词典
  • 来自外部词典的所有键都遵循模式前缀,后跟数字
  • 所有内部词汇共享相同的键,其值为数字
  • 输入公式描述了应该应用于内部dicts(由其键给出)的任意操作,或者更确切地说应用于其内部值

首先你需要处理你的dict键。我假设它们由前缀后跟数字组成。处理密钥将给出前缀(将用于处理公式)和下一个未使用的密钥(最大使用数字+1)。一旦指定了它,它就可以用Python编码,但正如我在评论中所说的那样,它是更难的部分:

def process_keys(dic):
    rx = re.compile("(\w*?)(\d+)")   # the pattern
    prefix = None
    mx = 0                           # maximum used value
    for key in dic.keys():
        m = rx.match(key)
        if m is None:                # every key must match the pattern
            raise ValueError(("key {} has not format "
                     +"prefix+number").format(key))
        if prefix is None:
            prefix = m.group(1)      # first processed key gives the prefix
        elif prefix != m.group(1):   # that must be used for all other ones
            raise ValueError(("key {} has not "
                     +"prefix {}").format(key, prefix))
        n = int(m.group(2))          # the current key value
        if n > mx: mx = n
    return "{}{}".format(prefix, mx+1), prefix

然后你必须预先处理公式。我假设公式是包含以下公式:

    来自dict的
  • 键应该被内部字典中的值替换
  • 运算符(目前以下代码只接受+和 - 运算符,但可以扩展为接受*,/和括号)。预处理将识别密钥和运算符,但是因为我们已经确定了前缀并且感谢re模块将是最简单的部分:

代码:

def process_formula(prefix, formula):
    rx = re.compile(r"({}\d+)|(\+|\-)".format(prefix))  # other operators could be added here
    return rx.findall(formula)

有趣的是,它返回(key, '')('', op)形式的2元组列表,因此将键与运算符区分开来是微不足道的。

现在我们可以将公式应用于dict。由于 eval是邪恶的,我将使用ast.litteral_eval并将公式中的键替换为内部字典中的值并连接字符串中的所有内容:

def gen_value(dic, cmd):
    inner_keys = list(list(dic.values())[0].keys())  # the keys of the inner dicts
    val = {}                              # prepare the new dict
    for k in inner_keys:
        c = ''                            # initialize the formula
        for x in cmd:
            if x[0] == '':                # for an operator just copy it
                c += x[1]
            else:
                c += str(dic[x[0]][k])    # if it was a key, copy the inner value
        val[k] = ast.literal_eval(c)      # populate resulting dic
    return val

好的,是时候把所有东西捆绑在一起了:

def process(dic, formula):
    key_ref = process_keys(dic)
    cmd = process_formula(key_ref[1], formula)
    dic[key_ref[0]] = gen_value(dic, cmd)

这个修改原始字典。留给读者如何建立一个新的词典...

答案 2 :(得分:0)

Pandas内置了对此类内容的支持,因为您的数据类似于表格,pandas.DataFrame看起来像是一种适合存储它们的数据类型。这就是您的数据看起来像DataFrame

import pandas as pd
df = pd.DataFrame(samples_dict)
print(df)

             sample1  sample2  sample3  sample4  sample5
Bhubaneswar     21.0   600.67    700.0   625.94   425.94
Mumbai          63.0  1000.01   2100.0  1877.82   877.82

有一个方法DataFrame.eval接受字符串并根据列标签将它们计算为表达式。

formula = 'sample6 = sample1 + sample2'
df.eval(formula, inplace=True)
print(df)

             sample1  sample2  sample3  sample4  sample5  sample6
Bhubaneswar     21.0   600.67    700.0   625.94   425.94   621.67
Mumbai          63.0  1000.01   2100.0  1877.82   877.82  1063.01

在这种情况下,公式的定义来自.eval的规范,这可能适合您的需求,但可能不符合您的需求。我不得不对公式中的新密钥进行硬编码,因为您没有提供任何以编程方式生成它的提示。