【问题标题】:Calculate delta in dictionary of dictionary计算字典字典中的增量
【发布时间】:2021-10-19 08:39:46
【问题描述】:

我有一本字典,其中包含这样的元组列表:

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)...()]}
               ...
 } 

我想计算字典内每个元组中第三个项目(它们的前两个项目相同)的增量,在每周之间(例如,第 1 周和第 2 周,.. 第 19 周和第 20 周)并将它们放入作为主词典中的新词典。所以我想要的结果可能是这样的:

    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)...()]
 } 

【问题讨论】:

  • 你是说每周和下周之间?你有没有尝试过任何你想分享的东西?
  • 元组列表是否已排序,下周前两个元组条目是否有一个?你已经尝试过什么?
  • 是的,例如,在第 1 周和第 2 周、第 2 周和第 3 周、第 3 周和第 4 周之间,等等。不,实际上我找不到开始的方法。
  • 元组已排序。
  • 您还需要 delta_wk2_wk3 还是成对进行 - 即 delta_wk1_wk2 然后 delta_wk3_wk4

标签: python pandas list numpy dictionary


【解决方案1】:

要获得每一对周,您可以使用成对迭代器,您可以查看 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)

【讨论】:

    【解决方案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.diff 和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.]]])
    

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

    【讨论】:

      猜你喜欢
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      相关资源
      最近更新 更多