2017-08-11 11 views
5

Rozważmy następujący hdfstore i dataframes df i df2Czy mogę zaktualizować HDFStore?

import pandas as pd 

store = pd.HDFStore('test.h5') 

midx = pd.MultiIndex.from_product([range(2), list('XYZ')], names=list('AB')) 
df = pd.DataFrame(dict(C=range(6)), midx) 

df 

    C 
A B 
0 X 0 
    Y 1 
    Z 2 
1 X 3 
    Y 4 
    Z 5 

midx2 = pd.MultiIndex.from_product([range(2), list('VWX')], names=list('AB')) 
df2 = pd.DataFrame(dict(C=range(6)), midx2) 

df2 

    C 
A B 
0 V 0 
    W 1 
    X 2 
1 V 3 
    W 4 
    X 5 

Chcę najpierw napisać df do sklepu.

store.append('df', df) 

store.get('df') 

    C 
A B 
0 X 0 
    Y 1 
    Z 2 
1 X 3 
    Y 4 
    Z 5 

W późniejszym czasie będzie mam inny dataframe że chcę zaktualizować sklepu z. Chcę zastąpić wiersze tymi samymi wartościami indeksu, jakie są w mojej nowej ramce danych, zachowując stare.

Kiedy zrobić

store.append('df', df2) 

store.get('df') 

    C 
A B 
0 X 0 
    Y 1 
    Z 2 
1 X 3 
    Y 4 
    Z 5 
0 V 0 
    W 1 
    X 2 
1 V 3 
    W 4 
    X 5 

To nie jest w ogóle to, co chcę. Zauważ, że (0, 'X') i (1, 'X') są powtarzane. Potrafię manipulować połączoną ramką danych i nadpisywać, ale spodziewam się pracować z dużą ilością danych, w których nie byłoby to możliwe.

Jak zaktualizować sklep, aby uzyskać?

 C 
A B 
0 V 0 
    W 1 
    X 2 
    Y 1 
    Z 2 
1 V 3 
    W 4 
    X 5 
    Y 4 
    Z 5 

Zobaczysz, że dla każdego poziomu 'A', 'Y' i 'Z' są takie same, 'V' i 'W' są nowe, a 'X' jest aktualizowana.

Jaki jest prawidłowy sposób to zrobić?

+0

można pracować z normalnymi indeksami (nie wielomaindeksami)? – MaxU

+0

Tak ... Moje rzeczywiste dane mają wiele indeksów, ale jeśli pokazujesz coś z pojedynczym indeksem, jestem z tego zadowolony. – piRSquared

+0

OK, potrzebuję trochę czasu na przygotowanie prezentacji ... – MaxU

Odpowiedz

3

Pomysł: Usuwanie dopasowanie rzędy (o takich samych wartościach indeksów) z HDF, a następnie dodać do df2 HDFStore.

Problem: Nie można znaleźć sposobu użycia where="index in df2.index" do indeksowania wielu indeksów.

Rozwiązanie: pierwsze multiindexes konwertować do normalnymi:

df.index = df.index.get_level_values(0).astype(str) + '_' + df.index.get_level_values(1).astype(str) 

df2.index = df2.index.get_level_values(0).astype(str) + '_' + df2.index.get_level_values(1).astype(str) 

Daje:

In [348]: df 
Out[348]: 
    C 
0_X 0 
0_Y 1 
0_Z 2 
1_X 3 
1_Y 4 
1_Z 5 

In [349]: df2 
Out[349]: 
    C 
0_V 0 
0_W 1 
0_X 2 
1_V 3 
1_W 4 
1_X 5 

upewnij się, że używasz format='t' i data_columns=True (wskaźnik ten będzie zapisać indeksu i indeksu wszystkich kolumn w pliku HDF5, co pozwala nam na użycie ich w klauzuli where) podczas tworzenia/dołączania plików HDF5:

store = pd.HDFStore('d:/temp/test1.h5') 
store.append('df', df, format='t', data_columns=True) 
store.close() 

teraz możemy najpierw usunąć te wiersze z HDFStore z pasującymi indeksów:

store = pd.HDFStore('d:/temp/test1.h5') 

In [345]: store.remove('df', where="index in df2.index") 
Out[345]: 2 

i dołączyć df2:

In [346]: store.append('df', df2, format='t', data_columns=True, append=True) 

Wynik:

In [347]: store.get('df') 
Out[347]: 
    C 
0_Y 1 
0_Z 2 
1_Y 4 
1_Z 5 
0_V 0 
0_W 1 
0_X 2 
1_V 3 
1_W 4 
1_X 5 
+1

Dziękuję bardzo! Wiele się tam nauczyłem. Mam teraz kilka pomysłów. Odpowiem z powrotem. – piRSquared

+0

@piRSquared, zadowolony, jeśli to pomaga. Tak, proszę podać krótki komentarz dotyczący ostatecznego rozwiązania. Pomoże to również osobom mającym ten sam problem ... – MaxU

+0

Występuje problem z składnią 'where =" index w df.index "'. Zobacz Pandas [bug # 17567] (https://github.com/pandas-dev/pandas/issues/17567), aby uzyskać wyjaśnienie i obejście tego problemu. –

Powiązane problemy