【问题标题】:Building a dictionary from a three dimensional array with Python使用 Python 从三维数组构建字典
【发布时间】:2018-10-17 18:18:51
【问题描述】:

我目前无法根据数组的第一列将我的 3d 数组数据分类到不同的字典中。我想检查数组的第一列,并用其中的字符串名称制作一个字典。我还想用同一行上的值制作一个二维数组。我的数据看起来像这样:

allValues=[["str1","str1","str1","str1","str1","str1","str1","str2","str2","str2","str2","str2"],[1,2,3,4,5,6,7,8,9,10,11,12],[1,2,3,4,5,6,7,8,9,10,11,12]] 

而我的目标是:

allValuesDict = {'str1': [[1,2,3,4,5,6,7], [1,2,3,4,5,6,7]], 'str2': [[8,9,10,11,12], [8,9,10,11,12]]}

【问题讨论】:

  • 我看到了一个二维数组。 'row' 和 'column' 在描述中也交换了。 'key' 列(第一行)是否已预先排序,每个唯一的数量是否与常规数组输出兼容?或者你有时会想要一个“衣衫褴褛的列表/字典”
  • 下面的答案有帮助吗?随意接受答案(左侧的绿色勾号),或要求澄清。

标签: python python-2.7 sorting dictionary multidimensional-array


【解决方案1】:

Pandas 是一个很好的工具。它产生相当可读的代码。

>>> import pandas as pd

>>> df = pd.DataFrame(allValues).T
>>> df
       0   1   2
0   str1   1   1
1   str1   2   2
2   str1   3   3
3   str1   4   4
4   str1   5   5
5   str1   6   6
6   str1   7   7
7   str2   8   8
8   str2   9   9
9   str2  10  10
10  str2  11  11
11  str2  12  12

>>> grouped = df.groupby(0)[[1,2]].apply(lambda l: list(zip(*pd.Series.tolist(l))))
>>> grouped
0
str1    [(1, 2, 3, 4, 5, 6, 7), (1, 2, 3, 4, 5, 6, 7)]
str2          [(8, 9, 10, 11, 12), (8, 9, 10, 11, 12)]
dtype: object

>>> grouped.to_dict()
{'str1': [(1, 2, 3, 4, 5, 6, 7), (1, 2, 3, 4, 5, 6, 7)], 'str2': [(8, 9, 10, 11, 12), (8, 9, 10, 11, 12)]}

【讨论】:

  • 我想,这就是我需要的。所以我可以很容易地用 mathplotlib 绘制曲线。能否简单介绍一下 groupby 函数?我的意思是那行: grouped = df.groupby(0)[[1,2]].apply(lambda l: list(zip(*pd.Series.tolist(l)))) 我找不到一个很好的例子在网上!
  • groupby 有点复杂...基本上,group df 在第 0 列(第一列)——你可以把 df 拆分成两个单独的数据帧,一个用于str1,另一个用于str2。然后,将每个中的行转换为Series(这里需要pandas-aware 类型;单独list 不起作用),将它们压缩以转换为列,并将压缩转换为列表,然后组合回来到一个数据框中。获取此数据框并将其转换为字典。
  • 好的,我觉得对我来说有点复杂。不过谢谢。有没有办法让它与 python 2.7 一起工作。似乎 tolist 函数正在工作(TypeError:未绑定的方法 tolist() 必须以 Series 实例作为第一个参数调用(改为获取 DataFrame 实例))
  • 如果您真的无法迁移到 Python 3,那么请不要使用 pandas 的解决方案,因为 pandas 将于 2019 年 1 月 1 日放弃对 Python 2.7 的支持。但您真的不应该使用Python 2.7 了。
【解决方案2】:

zip 可以将您的列表翻译成[['str1',1,1],['str2',2,2],...],这可以使迭代更容易:

allValues = [['str1','str1','str1','str1','str1','str1','str1','str2','str2','str2','str2','str2'],
             [1,2,3,4,5,6,7,8,9,10,11,12],
             [1,2,3,4,5,6,7,8,9,10,11,12]]

D = {}
for k,v1,v2 in zip(*allValues):
    if k in D:
        D[k][0].append(v1)
        D[k][1].append(v2)
    else:
        D[k] = [[v1],[v2]]

print D

输出:

{'str2': [[8, 9, 10, 11, 12], [8, 9, 10, 11, 12]], 'str1': [[1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]]}

使用defaultdict 可以进一步简化:

from collections import defaultdict

allValues = [['str1','str1','str1','str1','str1','str1','str1','str2','str2','str2','str2','str2'],
             [1,2,3,4,5,6,7,8,9,10,11,12],
             [1,2,3,4,5,6,7,8,9,10,11,12]]

D = defaultdict(lambda:[[],[]])
for k,v1,v2 in zip(*allValues):
    D[k][0].append(v1)
    D[k][1].append(v2)

print D
print dict(D)  # If you don't want the final type to be defaultdict.

输出:

defaultdict(<function <lambda> at 0x00000000070A5128>, {'str2': [[8, 9, 10, 11, 12], [8, 9, 10, 11, 12]], 'str1': [[1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]]})
{'str2': [[8, 9, 10, 11, 12], [8, 9, 10, 11, 12]], 'str1': [[1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]]}

【讨论】:

    【解决方案3】:

    您可以使用collections.defaultdict 获得 O(n) 解决方案。

    请注意,这是非常具体您当前拥有的数据结构:

    from collections import defaultdict
    
    d = defaultdict(lambda: [[], []])
    
    for i, j, k in zip(*allValues):
        d[i][0].append(j)
        d[i][1].append(k)
    

    如果你需要转换成普通的dict

    res = dict(d)
    
    print(res)
    
    {'str1': [[1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]],
     'str2': [[8, 9, 10, 11, 12], [8, 9, 10, 11, 12]]}
    

    【讨论】:

      【解决方案4】:

      您可以使用itertools.groupbyzip

      import itertools
      allValues=[["str1","str1","str1","str1","str1","str1","str1","str2","str2","str2","str2","str2"],[1,2,3,4,5,6,7,8,9,10,11,12],[1,2,3,4,5,6,7,8,9,10,11,12]] 
      main, *rest = allValues
      grouped_data = list(itertools.chain.from_iterable([[[a, [h for _, h in b]] for a, b in itertools.groupby(zip(main, i), key=lambda x:x[0])] for i in rest]))
      final_grouping = {a:[i for _, i in b] for a, b in itertools.groupby(sorted(grouped_data, key=lambda x:x[0]), key=lambda x:x[0])}
      

      输出:

      {'str1': [[1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]], 'str2': [[8, 9, 10, 11, 12], [8, 9, 10, 11, 12]]}
      

      【讨论】:

      • 不知道,但我不喜欢没有解释的DV,所以我+1。
      猜你喜欢
      • 2015-09-30
      • 2017-08-30
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 2016-12-10
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多