[英]Is there a better data structure than nested dictionaries to create a student database in python?
[英]Python: more efficient data structure than a nested dictionary of dictionaries of arrays?
我正在編寫一個 python-3.10 程序來預測大量對象的各種屬性的時間序列。 我當前選擇的用於在代碼內部收集結果然后寫入文件的數據結構是 arrays 字典的嵌套字典。例如,對於具有 3 個屬性的時間序列的兩個對象:
properties = {'obj1':{'time':np.arange(10),'x':np.random.randn(10),'vx':np.random.randn(10)},
'obj2': {'time':np.arange(15),'x':np.random.randn(15),'vx':np.random.randn(15)}}
我喜歡這種嵌套字典格式的原因是它訪問起來很直觀——外鍵是 object 名稱,內鍵是屬性名稱。 對應於每個內部鍵的元素是 numpy arrays 給出一些屬性的值作為時間的 function。 我的實際代碼生成了一個包含約 100,000 個對象(外鍵)的字典,每個對象都有約 100 個屬性(內鍵)記錄在約 1000 次(numpy 浮點數組)。
我注意到當我在我自己的巨大屬性字典(或它的子集)上執行np.savez('filename.npz',**properties)
時,它需要一段時間並且 output 文件大小是幾 GB(可能是因為np.savez 在后台調用 pickle,因為我的嵌套字典不是數組)。
是否有更高效的數據結構廣泛適用於我的用例? 是否值得從我的嵌套字典切換到 pandas 數據幀、numpy ndarray 或記錄 arrays,或某種類似表的對象的列表? 能夠以二進制 output 格式保存/加載文件會很好,該格式保留從 object 名稱到屬性的字典/數組/表/數據框的映射,當然還有每個屬性時間序列的名稱 arrays .
讓我們看看你的obj2
值,一個字典:
In [307]: dd={'time':np.arange(15),'x':np.random.randn(15),'vx':np.random.randn(15)}
In [308]: dd
Out[308]:
{'time': array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]),
'x': array([-0.48197915, 0.15597792, 0.44113401, 1.38062753, -1.21273378,
-1.27120008, 1.53072667, 1.9799255 , 0.13647925, -1.37056793,
-2.06470784, 0.92314969, 0.30885371, 0.64860014, 1.30273519]),
'vx': array([-1.60228105, -1.49163002, -1.17061046, -0.09267467, -0.94133092,
1.86391024, 1.006901 , -0.16168439, 1.5180135 , -1.16436363,
-0.20254291, -1.60280149, -1.91749387, 0.25366602, -1.61993012])}
從中很容易得到 dataframe:
In [309]: df = pd.DataFrame(dd)
In [310]: df
Out[310]:
time x vx
0 0 -0.481979 -1.602281
1 1 0.155978 -1.491630
2 2 0.441134 -1.170610
3 3 1.380628 -0.092675
4 4 -1.212734 -0.941331
5 5 -1.271200 1.863910
6 6 1.530727 1.006901
7 7 1.979926 -0.161684
8 8 0.136479 1.518014
9 9 -1.370568 -1.164364
10 10 -2.064708 -0.202543
11 11 0.923150 -1.602801
12 12 0.308854 -1.917494
13 13 0.648600 0.253666
14 14 1.302735 -1.619930
我們還可以從該框架制作結構化數組。 我也可以直接從你的字典創建數組,定義相同的復合數據類型。 但由於我已經有了框架,所以我將 go 這條路線。 結構化數組和 recarray 之間的區別很小。
In [312]: arr = df.to_records()
In [313]: arr
Out[313]:
rec.array([( 0, 0, -0.48197915, -1.60228105),
( 1, 1, 0.15597792, -1.49163002),
( 2, 2, 0.44113401, -1.17061046),
( 3, 3, 1.38062753, -0.09267467),
( 4, 4, -1.21273378, -0.94133092),
( 5, 5, -1.27120008, 1.86391024),
( 6, 6, 1.53072667, 1.006901 ),
( 7, 7, 1.9799255 , -0.16168439),
( 8, 8, 0.13647925, 1.5180135 ),
( 9, 9, -1.37056793, -1.16436363),
(10, 10, -2.06470784, -0.20254291),
(11, 11, 0.92314969, -1.60280149),
(12, 12, 0.30885371, -1.91749387),
(13, 13, 0.64860014, 0.25366602),
(14, 14, 1.30273519, -1.61993012)],
dtype=[('index', '<i8'), ('time', '<i4'), ('x', '<f8'), ('vx', '<f8')])
現在讓我們比較泡菜字符串:
In [314]: import pickle
In [315]: len(pickle.dumps(dd))
Out[315]: 561
In [316]: len(pickle.dumps(df)) # df.to_pickle makes a 1079 byte file
Out[316]: 1052
In [317]: len(pickle.dumps(arr)) # arr.nbytes is 420
Out[317]: 738 # np.save writes a 612 byte file
和其他編碼 - 列表:
In [318]: alist = list(dd.items())
In [319]: alist
Out[319]:
[('time', array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])),
('x',
array([-0.48197915, 0.15597792, 0.44113401, 1.38062753, -1.21273378,
-1.27120008, 1.53072667, 1.9799255 , 0.13647925, -1.37056793,
-2.06470784, 0.92314969, 0.30885371, 0.64860014, 1.30273519])),
('vx',
array([-1.60228105, -1.49163002, -1.17061046, -0.09267467, -0.94133092,
1.86391024, 1.006901 , -0.16168439, 1.5180135 , -1.16436363,
-0.20254291, -1.60280149, -1.91749387, 0.25366602, -1.61993012]))]
In [320]: len(pickle.dumps(alist))
Out[320]: 567
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.