简体   繁体   English

遍历Python字典中的部分元组键

[英]Iterate over part of tuple key in Python dictionary

I am working on an optimization project where I have a series of dictionaries with tuples as keys and another dictionary (a decision variable with Gurobi) where the key is the first element of the tuples in the other dictionaries. 我正在做一个优化项目,其中有一系列以元组为键的字典,还有另一个字典(Gurobi中的决策变量),其中键是其他字典中元组的第一个元素。 I need to be able to do the following: 我需要能够执行以下操作:

data1 = {(place, person): q}
data2 = {person: s}
x = {place: var}

qx = {k: x[k]*data1[k] for k in x}
total1 = {}
for key, value in qx.items():
    person = key[1]
    if person in total1:
        total1[person] = total1[person] + value
    else:
        total1[person] = value
total2 = {k: total1[k]/data2[k] for k in total1}

(Please note that the data1, data2, and x dictionaries are very large, 10,000+ distinct place/person pairs). (请注意,data1,data2和x字典非常大,超过10,000个不同的位置/人对)。

This same process works when I use the raw data in place of the decision variable, which uses the same (place, person) key. 当我使用原始数据代替使用相同(地点,人)键的决策变量时,此过程也有效。 Unfortunately, my variable within the Gurobi model itself must be a dictionary and it cannot contain the person key value. 不幸的是,我在Gurobi模型中的变量本身必须是字典,并且不能包含人员键值。

Is there any way to iterate over just the first value in the tuple key? 有什么方法可以迭代元组键中的第一个值吗?

EDIT: Here are some sample values (sensitive data, so placeholder values): 编辑:这是一些示例值(敏感数据,所以占位符值):

data1 = {(1, a): 28, (1, c): 57, (2, b): 125}
data2 = {a: 7.8, b: 8.5, c: 8.4}
x = {1: 0.002, 2: 0.013}

Values in data1 are all integers, data2 are hours, and x are small decimals. data1中的值都是整数,data2是小时,x是小数位。

Outputs in total2 should look similar to the following (assuming there are many other rows for each person): total2的输出应类似于以下内容(假设每个人还有许多其他行):

total2 = {a: 0.85, b: 1.2, c: 1.01}

This code is essentially calculating a "productivity score" for each person. 该代码本质上是为每个人计算“生产率得分”。 The decision variable, x, is looking only at each individual place for business purposes, so it cannot include the person identifiers. 决策变量x仅出于业务目的而在每个地方查看,因此它不能包含人员标识符。 Also, the Gurobi package is very limiting about how things can be formatted, so I have not found a way to even use the tuple key for x. 另外,Gurobi软件包在如何格式化方面有很大的局限性,因此我还没有找到一种甚至可以将元组键用于x的方法。

Generally, the most efficient way to aggregate values into bins is to use a for loop and store the values in a dictionary, as you did with total1 in your example. 通常,将值聚合到bin中的最有效方法是使用for循环并将值存储在字典中,就像在示例中对total1所做的那样。 In the code below, I have fixed your qx line so it runs, but I don't know if this matches your intention. 在下面的代码中,我已经修复了您的qx行,使其可以运行,但是我不知道这是否符合您的意图。 I also used total1.setdefault to streamline the code a little: 我还使用了total1.setdefault来简化代码:

a, b, c = 'a', 'b', 'c'
data1 = {(1, a): 28, (1, c): 57, (2, b): 125}
data2 = {a: 7.8, b: 8.5, c: 8.4}
x = {1: 0.002, 2: 0.013}

qx = {place, person: x[place] * value for (place, person), value in data1.items()}
total1 = {}
for (place, person), value in qx.items():
    total1.setdefault(person, 0.0)
    total1[person] += value
total2 = {k: total1[k] / data2[k] for k in total1}

print(total2)
# {'a': 0.0071794871794871795, 'c': 0.013571428571428571, 'b': 0.19117647058823528}

But this doesn't produce the result you asked for. 但这不会产生您要求的结果。 I can't tell at a glance how you get the result you showed, but this may help you move in the right direction. 我无法一目了然地告诉您如何获得显示的结果,但这可能有助于您朝着正确的方向前进。

It might also be easier to read if you moved the qx logic into the loop, like this: 如果将qx逻辑移入循环,则可能更容易阅读,如下所示:

total1 = {}
for (place, person), value in data1.items():
    total1.setdefault(person, 0.0)
    total1[person] += x[place] * value
total2 = {k: total1[k] / data2[k] for k in total1}

Or, if you want to do this often, it might be worth creating a cross-reference between persons and their matching places, as @martijn-pieters suggested (note, you still need a for loop to do the initial cross-referencing): 或者,如果您想经常执行此操作,则值得在人及其匹配位置之间创建交叉引用,如@ martijn-pieters建议的那样(请注意,您仍然需要一个for循环来进行初始交叉引用):

# create a list of valid places for each person
places_for_person = {}
for place, person in data1:
    places_for_person.setdefault(person, [])
    places_for_person[person].append(place)
# now do the calculation
total2 = {
    person: 
    sum(
        data1[place, person] * x[place]
        for place in places_for_person[person]
    ) / data2[person]
    for person in data2
}

For creating a new dictionary removing the tuple: 为了创建一个删除元组的新字典:

a, b, c = "a", "b", "c"
data1 = {(1, a): 28, (1, c): 57, (2, b): 125}
total = list()

spot = 0 
for a in data1:
    total.append(list(a[1])) # Add new Lists to list "total" containing the Key values
    total[spot].append(data1[a]) # Add Values to Keys judging from their spot in the list
    spot += 1 # to keep the spot in correct place in lists

total = dict(total) # convert it to dictionary
print(total)

Output: 输出:

{'a': 28, 'c': 57, 'b': 125}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM