2016-02-03 9 views
5

Chcę przechowywać DataFrame z różnymi kolumnami w pliku hdf5 (znajdź fragment z typami danych poniżej).Przechowywanie pand DataFrame z mieszanymi danymi i kategorią do hdf5

In [1]: mydf 
Out [1]: 
endTime    uint32 
distance   float16 
signature   category 
anchorName  category 
stationList   object 

Przed konwersji niektóre kolumny (podpis i NazwaKotwicy w moim fragmencie powyżej), użyłem kodu jak po jego przechowywania (który działa całkiem w porządku):

path = 'tmp4.hdf5' 
key = 'journeys' 
mydf.to_hdf(path, key, mode='w', complevel=9, complib='bzip2') 

Ale to nie działa z kategorii a następnie próbowałem następujące:

path = 'tmp4.hdf5' 
key = 'journeys' 
mydf.to_hdf(path, key, mode='w', format='t', complevel=9, complib='bzip2') 

To działa dobrze, jeśli usunąć kolumnę stationList, gdzie każdy wpis jest listą ciągów. Ale z tej kolumny mam następujący wyjątek:

Cannot serialize the column [stationList] because 
its data contents are [mixed] object dtype 

Jak muszę poprawić swój kod aby otrzymać ramka danych przechowywanej? Wersja

pandy: 0.17.1
python wersja: 2.7.6 (nie można go zmienić z przyczyn kompatybilności)


Edit1 (niektóre przykładowy kod):

import pandas as pd 

mydf = pd.DataFrame({'endTime' : pd.Series([1443525810,1443540836,1443609470]), 
        'distance' : pd.Series([454.75,477.25,242.12]), 
        'signature' : pd.Series(['ab','cd','ab']), 
        'anchorName' : pd.Series(['tec','ing','pol']), 
        'stationList' : pd.Series([['t1','t2','t3'],['4','t2','t3'],['t3','t2','t4']]) 
        }) 

# this works fine (no category) 
mydf.to_hdf('tmp_without_cat.hdf5', 'journeys', mode='w', complevel=9, complib='bzip2') 

for col in ['anchorName', 'signature']: 
    mydf[col] = mydf[col].astype('category') 

# this crashes now because of category data 
# mydf.to_hdf('tmp_with_cat.hdf5', 'journeys', mode='w', complevel=9, complib='bzip2') 

# switching to format='t' 
# this caused problems because of "mixed data" in column stationList 
mydf.to_hdf('tmp_with_cat.hdf5', 'journeys', mode='w', format='t', complevel=9, complib='bzip2') 

mydf.pop('stationList') 

# this again works fine 
mydf.to_hdf('tmp_with_cat_without_stationList.hdf5', 'journeys', mode='w', format='t', complevel=9, complib='bzip2') 

edit2: W międzyczasie próbowałem różnych rzeczy, aby pozbyć się tego problemu. Jednym z nich było przekonwertowanie wpisów kolumny stationList na tupele (możliwe, ponieważ nie zostaną one zmienione) oraz przekształcenie ich w kategorię. Ale nic to nie zmieniło. Oto linie I dodał po pętli konwersji (tylko dla kompletności):

mydf.stationList = [tuple(x) for x in mydf.stationList.values] 
mydf.stationList.astype('category') 
+0

Czy to jest pytanie? Pomoże to również opublikowanie rzeczywistego kodu w celu utworzenia testowej ramki danych. – Goyo

+0

To jest problem. Otrzymuję dane z innych plików, które były przechowywane przez inne skrypty. Spróbuję stworzyć podstawowe generowanie danych, które może pokazać mój problem. – AnnetteC

+0

Wygląda na to, że nie można już przechowywać zarówno kategorycznych, jak i list/krotek w tym samym formacie hdf5 (może to być naprawione w przyszłości). Nie mogę powiedzieć, co zmienić, nie wiedząc więcej o swoich wymaganiach. Może pozostawić ciągi jako łańcuchy, może wybrać inną reprezentację dla pozycji piku stacji ... jest zbyt wiele opcji. – Goyo

Odpowiedz

5

mieć dwa problemy:

  1. chcesz zapisać kategorycznych danych w pliku HDF5;
  2. Próbujesz przechowywać dowolne obiekty (np. stationList) w pliku HDF5.

Jak odkryłeś, dane kategoryczne (obecnie?) Są obsługiwane tylko w formacie "tabela" dla HDF5.

Jednak przechowywanie dowolnych obiektów (lista łańcuchów itp.) Nie jest czymś, co jest obsługiwane przez sam format HDF5. Pandy robią to za ciebie, serializując te obiekty za pomocą pikla, a następnie przechowując pikle jako ciąg o dowolnej długości (który nie jest obsługiwany przez wszystkie formaty HDF5, jak sądzę). Będzie to jednak wolne i nieefektywne, a HDF5 nigdy nie będzie dobrze obsługiwane.

W moim umyśle, masz dwie opcje:

  1. Pivot swoje dane tak masz jeden wiersz danych według nazwy stacji. Następnie możesz przechowywać wszystko w formacie pliku HDF5 w formacie tabeli. (Jest to ogólnie dobra praktyka, zobacz Hadley Wickham on Tidy Data.)
  2. Jeśli naprawdę chcesz zachować ten format, możesz równie dobrze zapisać całą ramkę danych za pomocą to_pickle(). Nie będzie to miało problemu z jakimkolwiek obiektem (np.lista łańcuchów itp.), którą rzucasz na to.

Osobiście polecam opcję 1. Można użyć szybkiego, binarnego formatu pliku. Pivot ułatwi również inne operacje na danych.

+1

Ten problem jest bardzo standardowy, ale rozwiązania są nieliczne – Tensor

Powiązane problemy