2014-04-28 1 views
0

팬더를 사용하여 CSV 파일을 hdf5 파일로 변환 할 때 결과 파일이 매우 큽니다. 예를 들어 170Mb의 테스트 csv 파일 (23 열, 130 만 행)은 2GB의 hdf5 파일을 생성합니다. 그러나 판다가 무시되고 hdf5 파일이 (pytables를 사용하여) 직접 작성된 경우 20Mb에 불과합니다. 다음 코드 (즉 팬더의 변환을 수행하는 데 사용됩니다)에서 dataframe에서 개체 컬럼의 값을 명시 적으로 (산세를 방지하기 위해) 문자열 객체로 변환됩니다 :팬더를 사용하여 CSV 파일을 HDF5로 변환

# Open the csv file as pandas data frame 
data = pd.read_csv(csvfilepath, sep=delimiter, low_memory=False) 

# Write the resulting data frame to the hdf5 file 
data.to_hdf(hdf5_file_path, table_name, format='table', complevel=9, 
      complib='lzo') 

이 점검을 HDF5 파일 (이다 사용 vitables는)

이었는지 이상하게 보인다하는 값이 (파이썬으로 표현된다는 점이다) 데이터 형식 (values_block0리스트 : INT, values_block1 : 플로트 values_block2 : 문자열) 대신에 하나의 특정 열의의 csv 파일의 모든 열. 이 때문에 파일 크기가 커지고 쿼리 시간에 어떤 영향을 주는지 궁금합니다.

약 1Tb가 변환되어야한다고 가정하면 결과 hdf5 파일의 크기를 줄이기 위해 수행 할 수있는 작업을 알고 싶습니다.

P. 나는이 question을 알고 있지만 큰 hdf5 파일 크기는 HDF5 형식 자체에 기인한다고 말합니다.이 경우에는 팬더를 우회하여 생성 된 hdf5 파일이 훨씬 작기 때문에이 경우에는 원인이 될 수 없습니다.

P.P.S. joris가 제안한대로 data.loc 대신 data.iloc를 사용해도 아무런 차이가 없습니다. 차이가없는 '전환'을 삭제했습니다. 제프의 ​​요청에 따라 읽기 dataframe에 대한 정보 :

<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1303331 entries, 0 to 1303330 
Columns: 23 entries, _PlanId to ACTIVITY_Gratis 
dtypes: float64(1), int64(5), object(17) 
+0

데이터 프레임에서 이러한 목록을 가져 오면 안되기 때문에 전환에 문제가있는 것은 확실합니다. 첫째,'str_cols'는 정수 위치입니다. 이 경우'data.loc [..]'대신'data.iloc [: str_cols] ='를 사용해야합니다. 그것은 이미 그것을 해결합니까? – joris

+0

csv를 읽은 직후에''df.info()''를 보여줍니다; 당신이하고있는 '전환'을 할 필요가 없습니다. – Jeff

+0

이 질문을 참조하십시오 : http : // stackoverflow.com/questions/20428355/appending-column-to-frame-of-hdf-file-in-pandas/20428786 # 20428786 및 docs : http://pandas.pydata.org/pandas-docs/stable/io.html – Jeff

답변

2

Here's 64 비트 리눅스에 0.13.1을 사용하여 다양한 입출력 방법

에 대한 회/크기의 비공식 비교

설정

In [3]: N = 1000000 

In [4]: df = DataFrame(dict([ ("int{0}".format(i),np.random.randint(0,10,size=N)) for i in range(5) ])) 

In [5]: df['float'] = np.random.randn(N) 

In [6]: from random import randrange 

In [8]: for i in range(10): 
    ...:  df["object_1_{0}".format(i)] = ['%08x'%randrange(16**8) for _ in range(N)] 
    ...:  

In [9]: for i in range(7): 
    ...:  df["object_2_{0}".format(i)] = ['%15x'%randrange(16**15) for _ in range(N)] 
    ...:  

In [11]: df.info() 
<class 'pandas.core.frame.DataFrame'> 
Int64Index: 1000000 entries, 0 to 999999 
Data columns (total 23 columns): 
int0   1000000 non-null int64 
int1   1000000 non-null int64 
int2   1000000 non-null int64 
int3   1000000 non-null int64 
int4   1000000 non-null int64 
float   1000000 non-null float64 
object_1_0 1000000 non-null object 
object_1_1 1000000 non-null object 
object_1_2 1000000 non-null object 
object_1_3 1000000 non-null object 
object_1_4 1000000 non-null object 
object_1_5 1000000 non-null object 
object_1_6 1000000 non-null object 
object_1_7 1000000 non-null object 
object_1_8 1000000 non-null object 
object_1_9 1000000 non-null object 
object_2_0 1000000 non-null object 
object_2_1 1000000 non-null object 
object_2_2 1000000 non-null object 
object_2_3 1000000 non-null object 
object_2_4 1000000 non-null object 
object_2_5 1000000 non-null object 
object_2_6 1000000 non-null object 
dtypes: float64(1), int64(5), object(17) 

types: float64(1), int64(5), object(17) 

다양한 방법

,784,313로 저장할210

디스크의 크기는 각 열에 대해 선택된 문자열 크기의 함수입니다. NO data_columns를 사용하면 ANY 문자열에 대해 가장 긴 크기를 사용합니다. 따라서 data_columns로 작성하면 크기가 커질 수 있습니다 (열이 많아서 열당 더 많은 공간이 필요합니다).

In [8]: DataFrame(dict(A = ['foo','bar','bah'], B = [1,2,3], C = [1.0,2.0,3.0], D=[4.0,5.0,6.0])).to_hdf('test.h5','data',mode='w',format='table') 

In [9]: !ptdump -avd test.h5 
/(RootGroup) '' 
    /._v_attrs (AttributeSet), 4 attributes: 
    [CLASS := 'GROUP', 
    PYTABLES_FORMAT_VERSION := '2.1', 
    TITLE := '', 
    VERSION := '1.0'] 
/data (Group) '' 
    /data._v_attrs (AttributeSet), 14 attributes: 
    [CLASS := 'GROUP', 
    TITLE := '', 
    VERSION := '1.0', 
    data_columns := [], 
    encoding := None, 
    index_cols := [(0, 'index')], 
    info := {1: {'type': 'Index', 'names': [None]}, 'index': {}}, 
    levels := 1, 
    nan_rep := 'nan', 
    non_index_axes := [(1, ['A', 'B', 'C', 'D'])], 
    pandas_type := 'frame_table', 
    pandas_version := '0.10.1', 
    table_type := 'appendable_frame', 
    values_cols := ['values_block_0', 'values_block_1', 'values_block_2']] 
/data/table (Table(3,)) '' 
    description := { 
    "index": Int64Col(shape=(), dflt=0, pos=0), 
    "values_block_0": Float64Col(shape=(2,), dflt=0.0, pos=1), 
    "values_block_1": Int64Col(shape=(1,), dflt=0, pos=2), 
    "values_block_2": StringCol(itemsize=3, shape=(1,), dflt='', pos=3)} 
    byteorder := 'little' 
    chunkshape := (1872,) 
    autoindex := True 
    colindexes := { 
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False} 
    /data/table._v_attrs (AttributeSet), 19 attributes: 
    [CLASS := 'TABLE', 
    FIELD_0_FILL := 0, 
    FIELD_0_NAME := 'index', 
    FIELD_1_FILL := 0.0, 
    FIELD_1_NAME := 'values_block_0', 
    FIELD_2_FILL := 0, 
    FIELD_2_NAME := 'values_block_1', 
    FIELD_3_FILL := '', 
    FIELD_3_NAME := 'values_block_2', 
    NROWS := 3, 
    TITLE := '', 
    VERSION := '2.7', 
    index_kind := 'integer', 
    values_block_0_dtype := 'float64', 
    values_block_0_kind := ['C', 'D'], 
    values_block_1_dtype := 'int64', 
    values_block_1_kind := ['B'], 
    values_block_2_dtype := 'string24', 
    values_block_2_kind := ['A']] 
    Data dump: 
[0] (0, [1.0, 4.0], [1], ['foo']) 
[1] (1, [2.0, 5.0], [2], ['bar']) 
[2] (2, [3.0, 6.0], [3], ['bah']) 

Dtypes가 블록으로 그룹화된다 (당신이 data_columns이있는 경우 그 때 별도) : 당신은 prob는 여기에 디스크 구조의 예입니다 here

을보고 제어 할 수 min_item_size을 지정합니다. 이것들은 단지 이런 식으로 인쇄됩니다; 그들은 배열처럼 저장됩니다.