在字典的字典中计算增量

2024-09-29 02:25:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一本字典,里面有元组列表,如下所示:

mydict:{'A1':{'week1': [(1,1,34),(1,2,3),(1,3,10),(2,1,3),(2,2,9)...()],
              'week2': [(1,1,4),(1,2,11),(1,3,8),(2,1,5),(2,2,7)...()],
               ...
              'week19': [(1,1,12),(1,2,13),(1,3,32),(2,1,45),(2,2,15)...()],
              'week20': [(1,1,43),(1,2,30),(1,3,6),(2,1,7),(2,2,4)...()]}
        'A2':{'week1': [(1,1,6),(1,2,4),(1,3,2),(2,1,87),(2,2,32)...()],
              'week2': [(1,1,32),(1,2,15),(1,3,43),(2,1,2),(2,2,12)...()],
               ...
              'week20': [(1,1,3),(1,2,3),(1,3,16),(2,1,17),(2,2,11)...()]}
               ...
 } 

我想计算字典内每个元组中每个星期(例如,第一周和第二周,…第十九周和第二十周)的第三项(前两项相同)的增量,并将它们作为主字典中的新字典。所以我想要的结果可能是这样的:

    out_dict:{'A1':{'week1': [(1,1,34),(1,2,3),(1,3,10),(2,1,3),(2,2,9)...()],
              'week2': [(1,1,4),(1,2,11),(1,3,8),(2,1,5),(2,2,7)...()],
                ...
              'week19': [(1,1,12),(1,2,13),(1,3,32),(2,1,45),(2,2,15)...()],
              'week20': [(1,1,43),(1,2,30),(1,3,6),(2,1,7),(2,2,4)...()],
              'delta_wk1_wk2':[(1,1,30),(1,2, 8),(1,3,2),(2,1,2),(2,2,2)...()],
              'delta_wk20_wk19':[(1,1,31),(1,2, 23),(1,3,26),(2,1,38),(2,2,11)...()]
              ...
   }
        'A2':{'week1': [(1,1,6),(1,2,4),(1,3,2),(2,1,87),(2,2,32)...()],
              'week2': [(1,1,32),(1,2,15),(1,3,43),(2,1,2),(2,2,12)...()],
              ...
              'week19': [(1,1,7),(1,2,0),(1,3,2),(2,1,33),(2,2,10)...()],
              'week20': [(1,1,3),(1,2,3),(1,3,16),(2,1,17),(2,2,11)...()]}
               ...
              'delta_wk1_wk2':[(1,1,26),(1,2, 11),(1,3,41),(2,1,85),(2,2,20)...()],
              'delta_wk20_wk19':[(1,1,4),(1,2, 3),(1,3,14),(2,1,14),(2,2,1)...()]
 } 

Tags: a2列表字典a1mydict元组deltawk2
2条回答

据我所知,这是一个使用Numpy的解决方案,因为它被标记了

我只使用了A1组的周数,有一点变化,以显示排序问题:

data = {
    'week8': [(1,1,34),(1,2,3),(1,3,10),(2,1,3),(2,2,9)],
    'week9': [(1,1,4),(1,2,11),(1,3,8),(2,1,5),(2,2,7)],
    'week10': [(1,1,12),(1,2,13),(1,3,32),(2,1,45),(2,2,15)],
    'week11': [(1,1,43),(1,2,30),(1,3,6),(2,1,7),(2,2,4)]
}

第一件事是确保键已排序,但给定了键

format there is an issue:
data_tmp = sorted(zip(data.keys(), data.values()))
list(data_tmp)

其结果是:

# [('week10', [(1, 1, 12), (1, 2, 13), (1, 3, 32), (2, 1, 45), (2, 2, 15)]),
#  ('week11', [(1, 1, 43), (1, 2, 30), (1, 3, 6), (2, 1, 7), (2, 2, 4)]),
#  ('week8', [(1, 1, 34), (1, 2, 3), (1, 3, 10), (2, 1, 3), (2, 2, 9)]),
#  ('week9', [(1, 1, 4), (1, 2, 11), (1, 3, 8), (2, 1, 5), (2, 2, 7)])]

首先,让我们定义一个将周数提取为整数的方法:

import re

def week_number(wk_string):
    tmp = [ch for ch in wk_string if ch.isdigit()]
    return int(('').join(tmp))

例如week_number('week43') #=> 43


让我们对数据进行排序

data_sorted = sorted(zip([week_number(wk_string) for wk_string in data.keys()], data.values()))
list(data_sorted)

# [(8, [(1, 1, 34), (1, 2, 3), (1, 3, 10), (2, 1, 3), (2, 2, 9)]),
#  (9, [(1, 1, 4), (1, 2, 11), (1, 3, 8), (2, 1, 5), (2, 2, 7)]),
#  (10, [(1, 1, 12), (1, 2, 13), (1, 3, 32), (2, 1, 45), (2, 2, 15)]),
#  (11, [(1, 1, 43), (1, 2, 30), (1, 3, 6), (2, 1, 7), (2, 2, 4)])]

方法就绪后,让我们将数据转换为维度为(week_number, i, j)的Numpy数组

考虑索引从0开始,所以要考虑它。

dim_w = 52
dim_i = max([e[0] for _, value in data_sorted for e in value ])
dim_i #=> 2
dim_j = max([e[1] for _, value in data_sorted for e in value ])
dim_j #=> 3

将数组初始化为零,然后循环以填充值:

import numpy as np

ary = np.zeros((52, dim_i, dim_j))

for num_week, week_data in data_sorted:
    for i, j, val in week_data:
        ary[num_week-1, i-1, j-1] = val

在这里,您可以看到所考虑的周(8到12)的值:

ary[7:11,:,:] # indexes starts from zero

# array([[[34.,  3., 10.],
#         [ 3.,  9.,  0.]],
# 
#        [[ 4., 11.,  8.],
#         [ 5.,  7.,  0.]],
# 
#        [[12., 13., 32.],
#         [45., 15.,  0.]],
# 
#        [[43., 30.,  6.],
#         [ 7.,  4.,  0.]]])

要获得相邻行之间的差异,只需使用^{}numpy.abs获得绝对值:

diff = np.abs(np.diff(ary, axis=0))

# just to see a slice of the result:
diff[5:12,:,:]

# array([[[ 0.,  0.,  0.],
#         [ 0.,  0.,  0.]],
# 
#        [[34.,  3., 10.],
#         [ 3.,  9.,  0.]],
# 
#        [[30.,  8.,  2.],
#         [ 2.,  2.,  0.]],
# 
#        [[ 8.,  2., 24.],
#         [40.,  8.,  0.]],
# 
#        [[31., 17., 26.],
#         [38., 11.,  0.]],
# 
#        [[43., 30.,  6.],
#         [ 7.,  4.,  0.]],
# 
#        [[ 0.,  0.,  0.],
#         [ 0.,  0.,  0.]]])

一旦得到结果,您就可以重建字典或任何您需要的东西

要获得每两周,您可以使用成对迭代器,您可以查看itertools配方以查看实现;看起来是这样的:

from itertools import tee

def pairwise(iterable):
    x, y = tee(iterable)
    next(y, None)
    return zip(x, y)

然后,您可以在词典的条目上使用:

def add_deltas(data):
    for first, second in pairwise(data.keys()):
        deltas = []
        for a, b in zip(data[first], data[second]):
            if b:
                deltas.append((a[0], a[1], abs(a[2] - b[2])))
        data[f'delta_{first}_{second}'] = deltas

使用此选项循环浏览字典:

for v in mydict.values():
    add_deltas(v)

相关问题 更多 >