将字典转换为numpy数组的Pythonic方法
这其实是关于编程风格的问题。
我在抓取网页数据,比如“温度: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,这两列对应的键是x和y2,实际上就是这两个缺失的键
7
试试用 pandas 的 Series,它就是为这个设计的。
import pandas as pd
s = pd.Series({'a':1, 'b':2, 'c':3})
s.values # a numpy array