是否可以在磁盘上存储镶木地板文件,同时追加并按索引检索行?

Is it possible to store a parquet file on disk, while appending, and also retrieving rows by index?

我有185个数据文件,总共有3000万行。每两个都有两列;我想用作索引的单个整数和 512 个整数的列表。

所以看起来像这样

IndexID Ids
1899317 [0, 47715, 1757, 9, 38994, 230, 12, 241, 12228...
22861131    [0, 48156, 154, 6304, 43611, 11, 9496, 8982, 1...
2163410 [0, 26039, 41156, 227, 860, 3320, 6673, 260, 1...
15760716    [0, 40883, 4086, 11, 5, 18559, 1923, 1494, 4, ...
12244098    [0, 45651, 4128, 227, 5, 10397, 995, 731, 9, 3...

数据太大,无法加载到内存中,但我想使用索引列表一次检索几百行。

我从这条评论中得到了使用 Parquet 的建议。 Most efficient way of saving a pandas dataframe or 2d numpy array into h5py, with each row a seperate key, using a column

我一直在看官方镶木地板python指南

https://arrow.apache.org/docs/python/parquet.html

快速镶木地板指南

https://fastparquet.readthedocs.io/en/latest/api.html

但我似乎无法找到任何方法来使用索引检索行,如果 table 存储在磁盘上,或者是否全部加载到内存中。

这可能吗?如果是这样,我将如何做这样的事情?

例如

ParquetTable[22861131, 15760716]

[0, 48156, 154, 6304, 43611, 11, 9496, 8982, 1... [0, 40883, 4086, 11, 5, 18559, 1923, 1494, 4, ...

Parquet 是一种列式数据存储,不适合您的用例。如果您的目标是存储太大而无法放入内存的数据,但仍然能够一次检索行进行处理,我建议您使用数据库。

最简单的数据库是 sqlite3,它内置于 Python 本身。 Sqlite 数据库存储为文件,而不需要您设置数据库系统。

在我们继续之前,您需要将您的列表列分解为 512 列,以 (1) 使它们更易于使用,以及 (2) 我不认为数据库系统天生就支持列表.

这是一个关于如何转储数据和检索所需行的最小示例:

# Creating sample data to work on
import pandas as pd
import numpy as np

df = pd.DataFrame(
        data=np.random.randint(low=1, high=1000, size=(1000, 3)),
        columns=['a', 'b', 'c'],
        index=pd.Series(range(1000), name='IndexID')
)

import sqlite3

# Write dataframes to database
with sqlite3.connect('sqlite.db') as conn:
    df.to_sql('data', con=conn, if_exists='append')

上面的代码将 df 的内容转储到您当前工作目录中名为 sqlite.db 的 sqlite 数据库中。注意 to_sql 调用中的 if_exists 选项;如果要覆盖现有数据库,则需要将其更改为 replace

当您想从同一工作目录中检索特定行时,您可以运行以下操作。下面的示例检索第 200 到第 210 个索引:

# How to read from database
with sqlite3.connect('sqlite.db') as conn:
    # `rowid` is a keyword in sqlite queries to represent the index
    query = "SELECT * FROM data WHERE rowid BETWEEN %d AND %d" % (200, 210)
    subset = pd.read_sql(query, con=conn)

print(subset)
# This prints the following
#     IndexID    a    b    c
# 0       199  704    3  423
# 1       200  590  299  767
# 2       201   45  953  560
# 3       202  237  662  746
# 4       203  123  920  275
# 5       204  453   10  370
# 6       205   35  628  602
# 7       206  957  465  735
# 8       207  602  810  154
# 9       208  927  796  352
# 10      209  969  130  217

有关在 sqlite3 和 pandas 之间移动数据的更多信息,我建议阅读这篇 https://www.dataquest.io/blog/python-pandas-databases/ and