2013-05-30 5 views
16

Chciałbym zmodyfikować niektóre wartości z kolumny w mojej DataFrame. W tej chwili mam view z select poprzez multi-index mojego oryginalnego df (i modyfikacja zmienia się df).Przypisywanie nowych wartości do plasterka z MultiIndex DataFrame

Oto przykład:

In [1]: arrays = [np.array(['bar', 'bar', 'baz', 'qux', 'qux', 'bar']), 
        np.array(['one', 'two', 'one', 'one', 'two', 'one']), 
        np.arange(0, 6, 1)] 
In [2]: df = pd.DataFrame(randn(6, 3), index=arrays, columns=['A', 'B', 'C']) 

In [3]: df 
        A   B   C 
bar one 0 -0.088671 1.902021 -0.540959 
    two 1 0.782919 -0.733581 -0.824522 
baz one 2 -0.827128 -0.849712 0.072431 
qux one 3 -0.328493 1.456945 0.587793 
    two 4 -1.466625 0.720638 0.976438 
bar one 5 -0.456558 1.163404 0.464295 

staram się zmieniać plaster df do wartości skalarnej:

In [4]: df.ix['bar', 'two', :]['A'] 
Out[4]: 
1 0.782919 
Name: A, dtype: float64 

In [5]: df.ix['bar', 'two', :]['A'] = 9999 
# df is unchanged 

naprawdę chcę zmodyfikować kilka wartości w kolumnie (a od indeksowanie zwraca wektor, a nie wartość skalarną, myślę, że byłoby to bardziej sensowne):

In [6]: df.ix['bar', 'one', :]['A'] = [999, 888] 
# again df remains unchanged 

Używam pand 0.11. Czy istnieje prosty sposób na zrobienie tego?

Obecnym rozwiązaniem jest odtworzenie pliku df z nowego i zmodyfikowanie wartości, które chcę. Ale nie jest elegancka i może być bardzo ciężka na złożonej ramie danych. Moim zdaniem problem powinien pochodzić z .ix i .loc nie zwracając widoku, ale kopię.

+0

dlaczego -1 głosowanie? Czy możesz przynajmniej to wyjaśnić? – HadiM

+0

+1 doskonałe pytanie, do mylącego problemu. Jedyne, co przychodzi mi do głowy, to fakt, że został odrzucony, ponieważ tytuł nie jest opisowy? (ale kto wie!) –

+1

Przepraszamy za tytuł, ale nie jestem native speakerem w języku angielskim, a temat jest nieco skomplikowany, więc trudno znaleźć dobre :-) Jeśli chcesz przesłać mi jeden tytuł, mogę zmienić obecny jeden. – HadiM

Odpowiedz

10

Sortuj ramka, a następnie wybrać/ustawić za krotki dla multi-index

In [12]: df = pd.DataFrame(randn(6, 3), index=arrays, columns=['A', 'B', 'C']) 

In [13]: df 
Out[13]: 
        A   B   C 
bar one 0 -0.694240 0.725163 0.131891 
    two 1 -0.729186 0.244860 0.530870 
baz one 2 0.757816 1.129989 0.893080 
qux one 3 -2.275694 0.680023 -1.054816 
    two 4 0.291889 -0.409024 -0.307302 
bar one 5 1.697974 -1.828872 -1.004187 

In [14]: df = df.sortlevel(0) 

In [15]: df 
Out[15]: 
        A   B   C 
bar one 0 -0.694240 0.725163 0.131891 
     5 1.697974 -1.828872 -1.004187 
    two 1 -0.729186 0.244860 0.530870 
baz one 2 0.757816 1.129989 0.893080 
qux one 3 -2.275694 0.680023 -1.054816 
    two 4 0.291889 -0.409024 -0.307302 

In [16]: df.loc[('bar','two'),'A'] = 9999 

In [17]: df 
Out[17]: 
        A   B   C 
bar one 0 -0.694240 0.725163 0.131891 
     5  1.697974 -1.828872 -1.004187 
    two 1 9999.000000 0.244860 0.530870 
baz one 2  0.757816 1.129989 0.893080 
qux one 3 -2.275694 0.680023 -1.054816 
    two 4  0.291889 -0.409024 -0.307302 

Można też zrobić to z obecnie sortowania jeśli podasz pełny indeks, na przykład

In [23]: df.loc[('bar','two',1),'A'] = 999 

In [24]: df 
Out[24]: 
        A   B   C 
bar one 0 -0.113216 0.878715 -0.183941 
    two 1 999.000000 -1.405693 0.253388 
baz one 2 0.441543 0.470768 1.155103 
qux one 3 -0.008763 0.917800 -0.699279 
    two 4 0.061586 0.537913 0.380175 
bar one 5 0.857231 1.144246 -2.369694 

Aby sprawdzić głębię sortowania

In [27]: df.index.lexsort_depth 
Out[27]: 0 

In [28]: df.sortlevel(0).index.lexsort_depth 
Out[28]: 3 

Ostatnia część pytania, przypisując z listy (należy pamiętać, że trzeba mieć samą liczbę elementów, jak starają się zastąpić) i to MUSI być posortowane do tego, aby zadziałało

+0

A więc wszystko zależy od sortowania ... Ok, wykorzystam to w przyszłości. Dziękuję za lewę! – HadiM

+1

tak, niech to stanie się twoim przyjacielem: http://pandas.pydata.org/pandas-docs/dev/indexing.html#the-need-for-sortedness – Jeff