2011-03-29 7 views
19

텍스트/숫자가 혼합 된 크기가 큰 (10s of GB) CSV 파일이있는 경우 동일한 내용으로 hdf5 파일을 만드는 가장 빠른 방법은 무엇입니까? 가능한 경우 h5py 모듈을 사용하고 싶습니다.Python으로 hdf5 파일을 작성하는 가장 빠른 방법은 무엇입니까?

아래의 장난감 예제에서 나는 hdf5에 데이터를 쓰는 데 매우 느리고 믿을 수 없을만큼 빠른 방법을 발견했습니다. hdf5에 10,000 행 정도의 덩어리로 쓰는 것이 가장 좋은 방법일까요? 또는 그러한 파일에 방대한 양의 데이터를 쓰는 더 좋은 방법이 있습니까?

import h5py 

n = 10000000 
f = h5py.File('foo.h5','w') 
dset = f.create_dataset('int',(n,),'i') 

# this is terribly slow 
for i in xrange(n): 
    dset[i] = i 

# instantaneous 
dset[...] = 42 
+0

는 NumPy와 배열로 읽고 전체 배열 – Benjamin

+1

@Benjamin을 전송하여 루프를 피하기 : 배열이 메모리에 개최 너무 큰 경우는 어떻게? –

+0

당신은 hdf5 파일을 어떻게 구조화하고 싶은지 생각해 볼 필요가 있다고 생각합니다. –

답변

5

저는 데이터를 청크하는 것을 피하고 데이터를 일련의 단일 배열 데이터 세트로 저장합니다 (Benjamin이 제안하는 라인을 따라). 방금 HDF5로 작업 한 엔터프라이즈 응용 프로그램의 출력을 완료했으며 약 450 억 개의 복합 데이터 유형을 각각 1 만 개의 데이터 배열이 포함 된 450,000 개의 데이터 세트로 포장 할 수있었습니다. 글쓰기와 읽기는 이제는 당분간은 당연한 것처럼 보이지만 처음에는 데이터를 청크하려고 할 때 고통스럽게 느려졌습니다.

그냥 생각해보십시오.

업데이트 :

이 내 실제 코드 (I 파이썬 대 C 코딩 해요,하지만 당신은 내가 뭘하는지의 아이디어를 얻을한다)에서 해제 및 명확성을 위해 수정 조각의 커플입니다. 나는 배열 (배열 당 10,000 개의 값)에 긴 부호없는 정수를 쓰고 있는데, 실제 값이 필요할 때 다시 읽는다.

이것이 필자의 일반적인 작성자 코드이다. 이 경우, 배열의 시퀀스에 긴 부호없는 정수 시퀀스를 작성하고 각 배열 시퀀스가 ​​생성 될 때 hdf5에로드하는 것입니다.

//Our dummy data: a rolling count of long unsigned integers 
long unsigned int k = 0UL; 
//We'll use this to store our dummy data, 10,000 at a time 
long unsigned int kValues[NUMPERDATASET]; 
//Create the SS adata files. 
hid_t ssdb = H5Fcreate(SSHDF, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); 
//NUMPERDATASET = 10,000, so we get a 1 x 10,000 array 
hsize_t dsDim[1] = {NUMPERDATASET}; 
//Create the data space. 
hid_t dSpace = H5Screate_simple(1, dsDim, NULL); 
//NUMDATASETS = MAXSSVALUE/NUMPERDATASET, where MAXSSVALUE = 4,500,000,000 
for (unsigned long int i = 0UL; i < NUMDATASETS; i++){ 
    for (unsigned long int j = 0UL; j < NUMPERDATASET; j++){ 
     kValues[j] = k; 
     k += 1UL; 
    } 
    //Create the data set. 
    dssSet = H5Dcreate2(ssdb, g_strdup_printf("%lu", i), H5T_NATIVE_ULONG, dSpace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); 
    //Write data to the data set. 
    H5Dwrite(dssSet, H5T_NATIVE_ULONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, kValues); 
    //Close the data set. 
    H5Dclose(dssSet); 
} 
//Release the data space 
H5Sclose(dSpace); 
//Close the data files. 
H5Fclose(ssdb); 

이것은 독자 코드의 약간 수정 된 버전입니다. 이를 수행하는보다 세련된 방법이 있습니다 (즉, 값을 얻기 위해 초평면을 사용할 수 있음). 그러나 이는 상당히 훈련 된 민첩한/BDD 개발 프로세스와 관련하여 가장 깨끗한 해결책이었습니다.

unsigned long int getValueByIndex(unsigned long int nnValue){ 
    //NUMPERDATASET = 10,000 
    unsigned long int ssValue[NUMPERDATASET]; 
    //MAXSSVALUE = 4,500,000,000; i takes the smaller value of MAXSSVALUE or nnValue 
    //to avoid index out of range error 
    unsigned long int i = MIN(MAXSSVALUE-1,nnValue); 
    //Open the data file in read-write mode. 
    hid_t db = H5Fopen(_indexFilePath, H5F_ACC_RDONLY, H5P_DEFAULT); 
    //Create the data set. In this case, each dataset consists of a array of 10,000 
    //unsigned long int and is named according to its integer division value of i divided 
    //by the number per data set. 
    hid_t dSet = H5Dopen(db, g_strdup_printf("%lu", i/NUMPERDATASET), H5P_DEFAULT); 
    //Read the data set array. 
    H5Dread(dSet, H5T_NATIVE_ULONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, ssValue); 
    //Close the data set. 
    H5Dclose(dSet); 
    //Close the data file. 
    H5Fclose(db); 
    //Return the indexed value by using the modulus of i divided by the number per dataset 
    return ssValue[i % NUMPERDATASET]; 
} 

주요 테이크

는 어레이의 원하는 값의 집합 배열 인덱스의 인덱스를 얻을 수있는 코드를 작성하여 정수 나눗셈과 개조 작업의 내부 루프이다. 이것이 분명하다면 h5py에서 비슷하거나 더 나은 것을 함께 모을 수있게하십시오. C에서는이 방법이 간단하고 읽기/쓰기 시간이 상당히 단축됩니다.청크 데이터 세트 솔루션 어쨌든 복합 데이터 세트로 압축을 사용할 수 없기 때문에 청킹의 명백한 위쪽은 논점입니다. 따라서 모든 화합물은 같은 방식으로 저장됩니다.

+0

가능하면 데이터가 어떻게 구성되어 있는지 좀 더 자세히 살펴 보시겠습니까? 구체적인 (코드) 예제를 제공 할 수 있다면 그 답을 기꺼이 받아 들일 것입니다. –

+0

코드로 응답을 업데이트했습니다. 이게 도움이되는지 알려주세요! – Marc

3

나는 이것이 가장 효율적인 방법이 있는지 확실하지 않습니다 (그리고 나는 그것을 사용한 적이; 난 그냥 함께 내가 독립적으로 사용했던 몇 가지 도구를 당기는 해요),하지만 당신은 csv 파일을 읽을 수 matplotlib helper methods for csv을 사용하여 수치적인 재 배열로 변환합니다.

전체 내용을 디스크에로드하는 것을 피하기 위해 청크로 csv 파일을 읽을 수도 있습니다. 그런 다음 재 배열 (또는 그 안의 조각)을 사용하여 h5py 데이터 세트 전체 (또는 큰 덩어리)를 씁니다. h5py가 recarrays를 처리하는 방법을 정확히 모르겠다.하지만 문서는 괜찮을 것이라고 알려준다.

가능한 경우 기본적으로 개별 요소를 반복하는 대신 큰 덩어리의 데이터를 한 번에 작성하십시오.

CSV 파일을 읽기위한 또 다른 가능성은 numpy.genfromtxt

당신은 키워드 usecols를 사용하여 원하는 열을 잡아 수 있으며, 만 제대로 skip_headerskip_footer 키워드를 설정하여 라인의 지정된 세트에서 읽을 수 있습니다.

3

numpy.loadtxt의 유연성을 사용하면 파일에서 데이터를 numpy array으로 가져오고 hdf5 데이터 세트를 초기화하는 데 적합합니다.

import h5py 
import numpy as np 

d = np.loadtxt('data.txt') 
h = h5py.File('data.hdf5', 'w') 
dset = h.create_dataset('data', data=d)