将字典转换为numpy数组的Pythonic方法

3 投票
2 回答
10974 浏览
提问于 2025-04-18 06:36

这其实是关于编程风格的问题。

我在抓取网页数据,比如“温度:51 - 62”,“高度:1000-1500”等等。抓到的结果会保存在一个字典里。

{"temperature": "51-62", "height":"1000-1500" ...... }

这个字典里的所有键和值都是字符串类型。每个键都可以对应多个可能的值。现在我想把这个字典转换成一个numpy数组或向量。我有以下几个担忧:

  • 每个键在数组中对应一个索引位置。
  • 每个可能的字符串值都要映射到一个整数。
  • 对于某些字典,有些键可能不存在。例如,我还有一个字典没有“温度”这个键,因为那个网页上没有这个字段。

我在想,怎么用Python写出一个既清晰又高效的转换方法。我考虑建立另一个字典,把键映射到向量的索引号,还有很多其他字典,把值映射到整数。

我还有一个问题,就是不确定某些键的范围。我想动态地跟踪字符串值和整数之间的映射关系。例如,我可能会发现key1将来可以映射到val1_8。

谢谢!

2 个回答

1
>>> # a sequence of dictionaries in an interable called 'data'
>>> # assuming that not all dicts have the same keys
>>> pprint(data)
  [{'x': 7.0, 'y1': 2.773, 'y2': 4.5, 'y3': 2.0},
   {'x': 0.081, 'y1': 1.171, 'y2': 4.44, 'y3': 2.576},
   {'y1': 0.671, 'y3': 3.173},
   {'x': 0.242, 'y2': 3.978, 'y3': 3.791},
   {'x': 0.323, 'y1': 2.088, 'y2': 3.602, 'y3': 4.43}]

>>> # get the unique keys across entire dataset
>>> keys = [list(dx.keys()) for dx in data]

>>> # flatten and coerce to 'set'
>>> keys = {itm for inner_list in keys for itm in inner_list}

>>> # create a map (look-up table) from each key 
>>> # to a column in a NumPy array

>>> LuT = dict(enumerate(keys))
>>> LuT
  {'y2': 0, 'y3': 1, 'y1': 2, 'x': 3}

>>> idx = list(LuT.values())

>>> # pre-allocate NUmPy array (100 rows is arbitrary)
>>> # number of columns is len(LuT.keys())

>>> D = NP.empty((100, len(LuT.keys())))

>>> keys = list(LuT.keys())
>>> keys
  [0, 1, 2, 3]

>>> # now populate the array from the original data using LuT
>>> for i, row in enumerate(data):
        D[i,:] = [ row.get(LuT[k], 0) for k in keys ]

>> D[:5,:]
  array([[ 4.5  ,  2.   ,  2.773,  7.   ],
         [ 4.44 ,  2.576,  1.171,  0.081],
         [ 0.   ,  3.173,  0.671,  0.   ],
         [ 3.978,  3.791,  0.   ,  0.242],
         [ 3.602,  4.43 ,  2.088,  0.323]])

将最后的结果(D的前五行)与上面的数据进行比较

注意,每一行(一个字典)中的顺序是保持不变的,即使这个字典的键不完整。换句话说,D的第二列总是对应于键为y2的值,等等,即使在数据中对应的行没有存储这个键的值;比如,看看数据中的第三行,它只有两个键值对,而在D的第三行中,第一列和最后一列都是0,这两列对应的键是xy2,实际上就是这两个缺失的键

7

试试用 pandas 的 Series,它就是为这个设计的。

import pandas as pd
s = pd.Series({'a':1, 'b':2, 'c':3})
s.values # a numpy array

撰写回答