在 python 中的两个对象之间存储和使用信息的最佳方式是什么?

What is the best way to store and use information between two objects in python?

我有一组names/id个对象(就生活中的对象而言,不是python个对象)。

为简单起见,这些对象的名称如下:

A, B, C, D, E ...

此类对象的数量约为2000个(未来可能会达到6000个左右)。

我正在尝试确定完成任务的最佳方式:在每对对象之间存储信息(param1、param2、...、paramN)的最佳方式是什么.看起来像下面的数据结构:

                A               B              C              D 
A             -          [param1, param2] [param1, param2] [param1, param2]

B      [param1, param2]        -          [param1, param2] [param1, param2]

C      [param1, param2]  [param1, param2]       -          [param1, param2]

D      [param1, param2]  [param1, param2] [param1, param2]        -

重要的是要考虑几个方面:

我的解决方案: 我使用了 pandas.DataFrame 模块。 对于每个参数:param1, param2, ... 我制作了单个三角形 tables: param1table, param2table, ... 填充后我将它们保存在 CSV 文件中:param1table.csv, param2table.csv, ....csv

在我的程序中,如果我需要成对的param1:A,B,我需要加载param1table.csv(pandas.read_csv)并查看值[A,B]存在return它,否则return[B,A]

我认为这不是有效的方法。

如果你想坚持使用 pd.DataFrame,你可以使用 MultiIindex (see docs) 和 Object_1Object_2 作为 indexParam_1Param_2 作为 columns。这将是更可取的,因为 DataFrame 不是为存储 list 对象而设计的。

您可以使用 np.triu 提取当前 DataFrame 的上三角,(returns 下三角归零),使用 .replace(0, np.nan).stack() 转换为长格式。从那里只需要使用 df.col.str.split(','), expand=True.

reset_index().split() list 个对象

您可以轻松确保只存储 Object_1Object_2 而不是 Object_2Object_1,并使用 df.loc[('Object_1', 'Object_2'), :] 访问您的参数。

您可以将结果存储在 .csvhdf 中,这对于 n * (n-1) / 2 行会更快一些 (see docs)。

举例说明:

import pandas as pd
import numpy as np
import string
from itertools import permutations

从一个简单的 DataFrame 开始,它看起来与您目前似乎正在使用的相似:

objs = [o for o in permutations(list(string.ascii_uppercase[:5]), 2)]
obj_1, obj_2 = zip(*objs)
params = [list(np.random.randint(low=0, high=10, size=2)) for j in range(len(objs))]
df = pd.DataFrame(data={'obj_1': obj_1, 'obj_2': obj_2, 'params': params})
df = df.set_index(['obj_1', 'obj_2']).unstack()

obj_2       A       B       C       D       E
obj_1                                        
A        None  [4, 7]  [7, 5]  [0, 5]  [3, 0]
B      [4, 6]    None  [0, 8]  [0, 7]  [7, 2]
C      [6, 9]  [6, 2]    None  [7, 8]  [3, 1]
D      [0, 0]  [2, 4]  [9, 8]    None  [1, 8]
E      [2, 3]  [8, 6]  [5, 7]  [5, 8]    None

假设 params 是对称的,让我们去掉下面的三角形:

mask = np.ones(df.shape,dtype='bool')
mask[np.tril_indices(len(df))] = False
df = df.where(mask)

obj_2      A       B       C       D       E
obj_1                                       
A        NaN  [4, 7]  [7, 5]  [0, 5]  [3, 0]
B        NaN     NaN  [0, 8]  [0, 7]  [7, 2]
C        NaN     NaN     NaN  [7, 8]  [3, 1]
D        NaN     NaN     NaN     NaN  [1, 8]
E        NaN     NaN     NaN     NaN     NaN

接下来转换为长格式并从 list:

中提取 params
df = df.stack()
df['param_1'], df['param_2'] = (zip(*df.params))

             params  param_1  param_2
obj_1 obj_2                          
A     B      [4, 7]        4        7
      C      [7, 5]        7        5
      D      [0, 5]        0        5
      E      [3, 0]        3        0
B     C      [0, 8]        0        8
      D      [0, 7]        0        7
      E      [7, 2]        7        2
C     D      [7, 8]        7        8
      E      [3, 1]        3        1
D     E      [1, 8]        1        8

所以我们不再需要 params:

df.drop('params', axis=1, inplace=True)

现在可以这样访问了:

df.loc[('B', 'C')]

param_1    0
param_2    8

或单独:

df.loc[('B', 'C'), 'param_1']

0

根据我的 ML 和数据科学经验,有两种在 python 脚本之间共享数据的常用方法:CSV 和 HDF5。如果 csv 最适合您,请尽可能长时间使用它,因为 HDF5 不能很好地处理非整数值。

如果您的磁盘容量有问题,只需压缩您的数据即可。
Pandas' read_csv() 非常了解大多数流行的压缩算法。

如果在加载时存在速度问题 — 将其分块然后分类。

此外,如果您的数据是 'mirrored',为什么不简单地对您的列进行名称排序,然后以正确的方式回忆它呢?例如:call(cell[B,A]) -> call(cell[A,B]) -> cell[B,A].

补充:对于某些极端情况,您可以单独保存每一行(不要忘记删除它的空白部分),然后为它创建某种缓存缓冲区最热门的电话。