我需要在现有的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}}
有人帮助我。
答案 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)
虽然你认为这很简单,但这是一个相当复杂的问题,真正需要拆分的是较小的部分。
假设:
首先你需要处理你的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
然后你必须预先处理公式。我假设公式是包含以下公式:
代码:
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
的规范,这可能适合您的需求,但可能不符合您的需求。我不得不对公式中的新密钥进行硬编码,因为您没有提供任何以编程方式生成它的提示。