我有一组对象的名称/ 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,... 我制作单独的三角形表: param1table,param2table,... 填写后我将它们保存在CSV文件中:< em> param1table.csv,param2table.csv,.... csv
在我的程序中,如果我需要成对param1:A,B,我需要加载 param1table.csv (pandas.read_csv)并查看值[A,B]是否存在返回它,否则返回[B,A]
我认为这不是有效的方法。
答案 0 :(得分:2)
根据我的ML和数据科学经验,有两种常见的方法可以在python脚本之间共享数据:CSV和HDF5。如果csv对你来说很好,请尽可能长时间使用它,因为HDF5不能很好地处理非整数值。
如果您的磁盘容量存在问题,只需压缩数据即可
Pandas'read_csv()
非常了解最流行的压缩算法。
如果加载速度问题 - 将其分块,然后对其进行分类。
此外,如果您的数据是“镜像”的,为什么不简单地命名您的列,然后以正确的方式调用它? E.G。:call(cell [B,A]) - &gt;呼叫(小区[A,B]) - &gt;细胞[B,A]。
添加:对于某些极端情况,您可以单独保存每一行(不要忘记剪切它的空白部分),然后为最常用的调用创建某种缓存缓冲区。
答案 1 :(得分:1)
如果您想坚持pd.DataFrame
,可以使用MultiIindex
see docs)Object_1
,Object_2
作为index
, Param_1
,Param_2
为columns
。这是首选,因为DataFrame
并非设计用于存储list
个对象。
您可以使用np.triu
提取当前DataFrame
的上三角形(返回归零的下三角形),使用.replace(0, np.nan)
和.stack()
转换为长整数形成。从那里只需要使用reset_index()
.split()
和list
df.col.str.split(','), expand=True
个对象。
您可以轻松确保仅存储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
接下来转换为长格式并从params
中提取list
:
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