1

我有一组对象的名称/标识(就生活中的对象而言,而不是 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] 所以我们只需要存储所有表格的 1/2
  • 我需要将此表保存在 tmp 目录中并在我的 python 应用程序的启动中加载
  • 我需要在我的 python 应用程序中快速从这个表中提取值

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

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

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

4

2 回答 2

2

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

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

如果加载时出现速度问题 - 将其分块,然后对其进行分类。

此外,如果您的数据是“镜像”的,为什么不简单地对您的列进行命名排序,然后以正确的方式调用它呢?例如:调用(细胞[B,A])-> 调用(细胞[A,B])-> 细胞[B,A]。

另外:对于某些极端情况,您可以单独保存每一行(不要忘记剪切其中的空白部分),然后为最流行的调用创建某种缓存缓冲区。

于 2016-05-16T13:07:18.810 回答
1

如果您想坚持使用pd.DataFrame, 您可以使用MultiIindex(参见文档) with Object_1, Object_2asindexParam_1, Param_2as columns。这将是可取的,因为DataFrame不是为存储list对象而设计的。

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

您可以轻松地确保您只存储Object_1Object_2不是Object_2,Object_1并使用df.loc[('Object_1', 'Object_2'), :].

您可以将结果存储在.csvorhdf中,这对于行会更快一些(请参阅文档n * (n-1) / 2

为了显示:

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
于 2016-05-16T13:04:44.623 回答