簡體   English   中英

Python:比 arrays 的嵌套字典更有效的數據結構?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM