Mam ramkę danych z wieloma indeksami z kolumnami „A” i „B”.
Czy istnieje sposób na wybranie wierszy przez filtrowanie według jednej kolumny z wieloma indeksami bez resetowania indeksu do indeksu jednej kolumny?
Na przykład.
# has multi-index (A,B)
df
#can I do this? I know this doesn't work because the index is multi-index so I need to specify a tuple
df.ix[df.A ==1]
python
pandas
dataframe
multi-index
tłumik
źródło
źródło
Odpowiedzi:
Jednym ze sposobów jest użycie
get_level_values
metody Index:In [11]: df Out[11]: 0 A B 1 4 1 2 5 2 3 6 3 In [12]: df.iloc[df.index.get_level_values('A') == 1] Out[12]: 0 A B 1 4 1
W 0.13 będziesz mógł używać
xs
zdrop_level
argumentem :df.xs(1, level='A', drop_level=False) # axis=1 if columns
Uwaga: gdyby była to kolumna MultiIndex zamiast indeksu, możesz użyć tej samej techniki:
In [21]: df1 = df.T In [22]: df1.iloc[:, df1.columns.get_level_values('A') == 1] Out[22]: A 1 B 4 0 1
źródło
Możesz także użyć,
query
który moim zdaniem jest bardzo czytelny i prosty w użyciu:import pandas as pd df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [10, 20, 50, 80], 'C': [6, 7, 8, 9]}) df = df.set_index(['A', 'B']) C A B 1 10 6 2 20 7 3 50 8 4 80 9
To, co miałeś na myśli, możesz teraz po prostu zrobić:
df.query('A == 1') C A B 1 10 6
Możesz również mieć bardziej złożone zapytania przy użyciu
and
df.query('A >= 1 and B >= 50') C A B 3 50 8 4 80 9
i
or
df.query('A == 1 or B >= 50') C A B 1 10 6 3 50 8 4 80 9
Możesz również wykonywać zapytania na różnych poziomach indeksu , np
df.query('A == 1 or C >= 8')
wróci
C A B 1 10 6 3 50 8 4 80 9
Jeśli chcesz używać zmiennych w zapytaniu, możesz użyć
@
:b_threshold = 20 c_threshold = 8 df.query('B >= @b_threshold and C <= @c_threshold') C A B 2 20 7 3 50 8
źródło
df.query('A == 1 or C >= 8')
df.query()
działa dobrze ze zmiennymi, jeśli odwołuje się do nich za pomocą „@” wewnątrz wyrażenia w zapytaniu, np.df.query('A == @var
) Dla zmiennejvar
w środowisku.Możesz użyć
DataFrame.xs()
:In [36]: df = DataFrame(np.random.randn(10, 4)) In [37]: df.columns = [np.random.choice(['a', 'b'], size=4).tolist(), np.random.choice(['c', 'd'], size=4)] In [38]: df.columns.names = ['A', 'B'] In [39]: df Out[39]: A b a B d d d d 0 -1.406 0.548 -0.635 0.576 1 -0.212 -0.583 1.012 -1.377 2 0.951 -0.349 -0.477 -1.230 3 0.451 -0.168 0.949 0.545 4 -0.362 -0.855 1.676 -2.881 5 1.283 1.027 0.085 -1.282 6 0.583 -1.406 0.327 -0.146 7 -0.518 -0.480 0.139 0.851 8 -0.030 -0.630 -1.534 0.534 9 0.246 -1.558 -1.885 -1.543 In [40]: df.xs('a', level='A', axis=1) Out[40]: B d d 0 -0.635 0.576 1 1.012 -1.377 2 -0.477 -1.230 3 0.949 0.545 4 1.676 -2.881 5 0.085 -1.282 6 0.327 -0.146 7 0.139 0.851 8 -1.534 0.534 9 -1.885 -1.543
Jeśli chcesz zachować
A
poziom (drop_level
argument słowa kluczowego jest dostępny tylko od wersji 0.13.0):In [42]: df.xs('a', level='A', axis=1, drop_level=False) Out[42]: A a B d d 0 -0.635 0.576 1 1.012 -1.377 2 -0.477 -1.230 3 0.949 0.545 4 1.676 -2.881 5 0.085 -1.282 6 0.327 -0.146 7 0.139 0.851 8 -1.534 0.534 9 -1.885 -1.543
źródło
Zrozumienie, jak uzyskać dostęp do pand z wieloma indeksami DataFrame, może pomóc Ci w takich zadaniach.
Skopiuj, wklej to do swojego kodu, aby wygenerować przykład:
# hierarchical indices and columns index = pd.MultiIndex.from_product([[2013, 2014], [1, 2]], names=['year', 'visit']) columns = pd.MultiIndex.from_product([['Bob', 'Guido', 'Sue'], ['HR', 'Temp']], names=['subject', 'type']) # mock some data data = np.round(np.random.randn(4, 6), 1) data[:, ::2] *= 10 data += 37 # create the DataFrame health_data = pd.DataFrame(data, index=index, columns=columns) health_data
Da ci taki stół:
Dostęp standardowy według kolumny
health_data['Bob'] type HR Temp year visit 2013 1 22.0 38.6 2 52.0 38.3 2014 1 30.0 38.9 2 31.0 37.3 health_data['Bob']['HR'] year visit 2013 1 22.0 2 52.0 2014 1 30.0 2 31.0 Name: HR, dtype: float64 # filtering by column/subcolumn - your case: health_data['Bob']['HR']==22 year visit 2013 1 True 2 False 2014 1 False 2 False health_data['Bob']['HR'][2013] visit 1 22.0 2 52.0 Name: HR, dtype: float64 health_data['Bob']['HR'][2013][1] 22.0
Dostęp według rzędu
health_data.loc[2013] subject Bob Guido Sue type HR Temp HR Temp HR Temp visit 1 22.0 38.6 40.0 38.9 53.0 37.5 2 52.0 38.3 42.0 34.6 30.0 37.7 health_data.loc[2013,1] subject type Bob HR 22.0 Temp 38.6 Guido HR 40.0 Temp 38.9 Sue HR 53.0 Temp 37.5 Name: (2013, 1), dtype: float64 health_data.loc[2013,1]['Bob'] type HR 22.0 Temp 38.6 Name: (2013, 1), dtype: float64 health_data.loc[2013,1]['Bob']['HR'] 22.0
Wycinanie wielu indeksów
idx=pd.IndexSlice health_data.loc[idx[:,1], idx[:,'HR']] subject Bob Guido Sue type HR HR HR year visit 2013 1 22.0 40.0 53.0 2014 1 30.0 52.0 45.0
źródło
ValueError: cannot handle a non-unique multi-index!
błądMożesz użyć
DataFrame.loc
:>>> df.loc[1]
Przykład
>>> print(df) result A B C 1 1 1 6 2 9 2 1 8 2 11 2 1 1 7 2 10 2 1 9 2 12 >>> print(df.loc[1]) result B C 1 1 6 2 9 2 1 8 2 11 >>> print(df.loc[2, 1]) result C 1 7 2 10
źródło
df.loc[0], df.loc[1]....df.loc[n]
Inną opcją jest:
filter1 = df.index.get_level_values('A') == 1 filter2 = df.index.get_level_values('B') == 4 df.iloc[filter1 & filter2] Out[11]: 0 A B 1 4 1
źródło