在 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] -
重要的是要考虑几个方面:
- cell[A,B]=cell[B,A] 所以我们只需要存储所有 table
的 1/2
- 我需要将此 table 保存在 tmp 目录中并在我的 python 应用程序启动时加载
- 我需要在我的 python 应用程序中快速从这个 table 中提取价值
我的解决方案:
我使用了 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_1
,Object_2
作为 index
和 Param_1
,Param_2
作为 columns
。这将是更可取的,因为 DataFrame
不是为存储 list
对象而设计的。
您可以使用 np.triu
提取当前 DataFrame
的上三角,(returns 下三角归零),使用 .replace(0, np.nan)
和 .stack()
转换为长格式。从那里只需要使用 df.col.str.split(','), expand=True
.
reset_index()
和 .split()
list
个对象
您可以轻松确保只存储 Object_1
、Object_2
而不是 Object_2
、Object_1
,并使用 df.loc[('Object_1', 'Object_2'), :]
访问您的参数。
您可以将结果存储在 .csv
或 hdf
中,这对于 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].
补充:对于某些极端情况,您可以单独保存每一行(不要忘记删除它的空白部分),然后为它创建某种缓存缓冲区最热门的电话。
我有一组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] -
重要的是要考虑几个方面:
- cell[A,B]=cell[B,A] 所以我们只需要存储所有 table 的 1/2
- 我需要将此 table 保存在 tmp 目录中并在我的 python 应用程序启动时加载
- 我需要在我的 python 应用程序中快速从这个 table 中提取价值
我的解决方案: 我使用了 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_1
,Object_2
作为 index
和 Param_1
,Param_2
作为 columns
。这将是更可取的,因为 DataFrame
不是为存储 list
对象而设计的。
您可以使用 np.triu
提取当前 DataFrame
的上三角,(returns 下三角归零),使用 .replace(0, np.nan)
和 .stack()
转换为长格式。从那里只需要使用 df.col.str.split(','), expand=True
.
reset_index()
和 .split()
list
个对象
您可以轻松确保只存储 Object_1
、Object_2
而不是 Object_2
、Object_1
,并使用 df.loc[('Object_1', 'Object_2'), :]
访问您的参数。
您可以将结果存储在 .csv
或 hdf
中,这对于 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].
补充:对于某些极端情况,您可以单独保存每一行(不要忘记删除它的空白部分),然后为它创建某种缓存缓冲区最热门的电话。