簡體   English   中英

將大 csv 轉換為 hdf5

[英]Convert large csv to hdf5

我有一個 100M 行的 csv 文件(實際上是許多單獨的 csv 文件)總計 84GB。 我需要將其轉換為具有單個浮點數據集的 HDF5 文件。 我在測試中使用h5py沒有任何問題,但現在我無法在沒有用完 memory 的情況下完成最終數據集。

如何寫入 HDF5 而不必將整個數據集存儲在 memory 中? 我期待這里的實際代碼,因為它應該非常簡單。

我只是在查看pytables ,但它看起來不像數組 class (對應於 HDF5 數據集)可以迭代寫入。 同樣, pandas在其io_tools中有read_csvto_hdf方法,但我無法一次加載整個數據集,因此無法正常工作。 也許你可以用pytables或pandas中的其他工具幫助我正確解決問題。

在對to_hdf的調用中使用append=True

import numpy as np
import pandas as pd

filename = '/tmp/test.h5'

df = pd.DataFrame(np.arange(10).reshape((5,2)), columns=['A', 'B'])
print(df)
#    A  B
# 0  0  1
# 1  2  3
# 2  4  5
# 3  6  7
# 4  8  9

# Save to HDF5
df.to_hdf(filename, 'data', mode='w', format='table')
del df    # allow df to be garbage collected

# Append more data
df2 = pd.DataFrame(np.arange(10).reshape((5,2))*10, columns=['A', 'B'])
df2.to_hdf(filename, 'data', append=True)

print(pd.read_hdf(filename, 'data'))

產量

    A   B
0   0   1
1   2   3
2   4   5
3   6   7
4   8   9
0   0  10
1  20  30
2  40  50
3  60  70
4  80  90

請注意,在第一次調用df.to_hdf需要使用format='table'來使表可附加。 否則,默認情況下格式為'fixed' ,讀取和寫入速度更快,但會創建一個無法追加的表格。

因此,您可以一次處理一個CSV,使用append=True來構建hdf5文件。 然后覆蓋DataFrame或使用del df以允許舊的DataFrame被垃圾收集。


或者,而不是調用df.to_hdf ,你可以追加到一個HDFStore

import numpy as np
import pandas as pd

filename = '/tmp/test.h5'
store = pd.HDFStore(filename)

for i in range(2):
    df = pd.DataFrame(np.arange(10).reshape((5,2)) * 10**i, columns=['A', 'B'])
    store.append('data', df)

store.close()

store = pd.HDFStore(filename)
data = store['data']
print(data)
store.close()

產量

    A   B
0   0   1
1   2   3
2   4   5
3   6   7
4   8   9
0   0  10
1  20  30
2  40  50
3  60  70
4  80  90

PyTables應該可以實現這一點。 但是你需要使用EArray類。

作為示例,以下是我編寫的腳本,用於將存儲為.npy文件的分塊訓練數據導入單個.h5文件中。

import numpy
import tables
import os

training_data = tables.open_file('nn_training.h5', mode='w')
a = tables.Float64Atom()
bl_filter = tables.Filters(5, 'blosc')   # fast compressor at a moderate setting

training_input =  training_data.create_earray(training_data.root, 'X', a,
                                             (0, 1323), 'Training Input',
                                             bl_filter, 4000000)
training_output = training_data.create_earray(training_data.root, 'Y', a,
                                             (0, 27), 'Training Output',
                                             bl_filter, 4000000)

for filename in os.listdir('input'):
    print "loading {}...".format(filename)
    a = numpy.load(os.path.join('input', filename))
    print "writing to h5"
    training_input.append(a)

for filename in os.listdir('output'):
    print "loading {}...".format(filename)
    training_output.append(numpy.load(os.path.join('output', filename)))

查看文檔以獲取詳細說明,但非常簡單地說, create_earray函數需要1)數據根節點或父節點; 2)數組名稱; 3)數據類型原子; 4)要擴展的尺寸為0的形狀; 5)詳細的描述符; 6) 壓縮過濾器 ; 7)沿可擴展維度的預期行數。 只需要前兩個,但你可能會在實踐中使用全部七個。 該函數也接受一些其他可選參數; 再次,請參閱文檔了解詳細信息。

創建數組后,您可以按預期方式使用其append方法。

如果您有一個非常大的單個CSV 文件,您可能希望將 stream 轉換為 hdf,例如:

import numpy as np
import pandas as pd
from IPython.display import clear_output

CHUNK_SIZE = 5000000 

filename = 'data.csv'
dtypes = {'latitude': float, 'longitude': float}

iter_csv = pd.read_csv(
    filename, iterator=True,
    dtype=dtypes, encoding='utf-8', chunksize=CHUNK_SIZE)

cnt = 0
for ix, chunk in enumerate(iter_csv):
    chunk.to_hdf(
        "data.hdf", 'data', format='table', append=True)
    cnt += CHUNK_SIZE
    clear_output(wait=True)
    print(f"Processed {cnt:,.0f} coordinates..")

使用 64GB CSV 文件和 4.5 億坐標(約 10 分鍾轉換)進行測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM