在Python中存储和重新加载大型多维数据集

6 投票
3 回答
2867 浏览
提问于 2025-04-16 12:11

我将进行大量的模拟实验,产生很多数据,这些数据需要存储并在以后访问。我的模拟程序会把输出数据写入文本文件(每次模拟一个文件)。我打算写一个Python程序来读取这些文本文件,然后把数据存储成更方便后续分析的格式。经过一番搜索,我觉得信息量太大了,所以我在Stack Overflow上寻求一些建议。以下是具体情况:

我的数据基本上会呈现为一个多维数组,每个条目大概是这样的:

data[ stringArg1, stringArg2, stringArg3, stringArg4, intArg1 ] = [ floatResult01, floatResult02, ..., floatResult12 ]

每个参数大概有以下可能的值:

stringArg1: 50

stringArg2: 20

stringArg3: 6

stringArg4: 24

intArg1: 10,000

不过要注意,数据集会是稀疏的。比如,对于某个特定的stringArg1值,只有大约16个stringArg2的值会被填充。而对于某个特定的(stringArg1, stringArg2)组合,大约会填充5000个intArg1的值。第三和第四个字符串参数总是会完全填充。

所以,根据这些数字,我的数组大概会有50*16*6*24*5000 = 576,000,000个结果列表。

我在寻找最佳的方式来存储这个数组,以便我可以保存它并在以后重新打开,添加更多数据、更新已有数据,或者查询现有数据进行分析。到目前为止,我考虑了三种不同的方法:

  1. 关系型数据库

  2. PyTables

  3. 使用元组作为字典键的Python字典(使用pickle保存和加载)

不过在这三种方法中,我总是遇到一个问题,我最终总是需要存储每个元组组合(stringArg1, stringArg2, stringArg3, stringArg4, intArg1),无论是作为表中的字段,还是作为Python字典中的键。从我(可能有些天真的)角度来看,这似乎不是必要的。如果这些都是整数参数,它们就可以形成数组中每个数据条目的地址,而不需要在单独的字段中存储所有可能的地址组合。例如,如果我有一个2x2的数组 = [[100, 200] , [300, 400]],你可以通过请求地址array[0][1]来获取值。你不需要把所有可能的地址元组(0,0) (0,1) (1,0) (1,1)存储在其他地方。所以我希望能找到一个解决办法。

我希望能够在PyTables中定义一个表,其中第一个表的单元格包含其他表。例如,顶层表会有两列。第一列的条目是stringArg1的可能值。第二列的每个条目都是一个表。这些子表会有两列,第一列是所有可能的stringArg2值,第二列是另一个子表的列……

这种解决方案会很容易浏览和查询(特别是如果我可以使用ViTables来浏览数据)。问题是PyTables似乎不支持一个表的单元格包含其他表。所以我在这方面似乎遇到了瓶颈。

我一直在研究数据仓库和星型模式的方法,但看起来你的事实表仍然需要包含每个可能参数组合的元组。

好吧,这就是我目前的情况。任何建议都将非常感激。到现在为止,我搜索得太多,脑袋都疼了。我觉得是时候向专家请教了。

3 个回答

0

我不太确定你想要做什么,但看起来你是在尝试创建一个(可能是稀疏的)多维数组。所以我不会详细讲解你具体的问题,但我知道的最好的处理这个的工具是 Numpy Numpy

Numpy 可以用作一个高效的多维数据容器。你可以定义任意的数据类型。这让 Numpy 能够与各种数据库无缝且快速地结合在一起。

我多次使用 Numpy 来处理模拟数据,它提供了很多有用的工具,包括方便的文件存储和访问。

希望你能在它非常易读的文档中找到一些有用的信息:

Numpy 文档及示例

0

有没有什么原因让基本的6个表的方法不适用呢?

也就是说,表1到表5都是单列的表,用来定义每个字段的有效值,然后最后一个表就是一个有5列的表,用来定义实际存在的条目。

另外,如果你说的第三和第四个字符串值总是存在的话,第六个表可以只包含3列(string1, string2, int1),然后通过笛卡尔连接动态生成string3和string4的组合。

2

为什么不使用一个大表来存储所有5亿条记录呢?如果你使用实时压缩(这里推荐使用Blosc压缩器),大部分重复的记录会被去掉,这样存储的空间就能保持在最低限度。我建议你试试看;有时候简单的解决方案效果最好哦;-)

撰写回答