Jak wybrać wiersze z DataFrame na podstawie wartości kolumn?

1953

Jak wybrać wiersze z DataFrame podstawie wartości w niektórych kolumnach w Python Pandas?

W SQL użyłbym:

SELECT *
FROM table
WHERE colume_name = some_value

Próbowałem przejrzeć dokumentację pand, ale nie znalazłem od razu odpowiedzi.

szli
źródło
6
To jest porównanie z SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html, gdzie można uruchamiać pandy jako SQL.
i_thamary

Odpowiedzi:

3757

Aby wybrać wiersze, których wartość kolumny jest równa skalarowi some_value, użyj ==:

df.loc[df['column_name'] == some_value]

Aby wybrać wiersze, których wartość kolumny jest iterowalna some_values, użyj isin:

df.loc[df['column_name'].isin(some_values)]

Połącz wiele warunków z &:

df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]

Zwróć uwagę na nawiasy. Ze względu na reguły pierwszeństwa operatora Pythona , &wiązania są ściślejsze niż <=i >=. Dlatego nawiasy w ostatnim przykładzie są konieczne. Bez nawiasów

df['column_name'] >= A & df['column_name'] <= B

jest analizowany jako

df['column_name'] >= (A & df['column_name']) <= B

co powoduje, że wartość Prawdy Serii jest niejednoznacznym błędem .


Aby wybrać wiersze, których wartość kolumny nie jest równa some_value , użyj !=:

df.loc[df['column_name'] != some_value]

isinZwraca wartość logiczną z serii, tak aby wybrać wiersze, których wartość jest nie w some_values, neguje logiczną Series przy użyciu ~:

df.loc[~df['column_name'].isin(some_values)]

Na przykład,

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})
print(df)
#      A      B  C   D
# 0  foo    one  0   0
# 1  bar    one  1   2
# 2  foo    two  2   4
# 3  bar  three  3   6
# 4  foo    two  4   8
# 5  bar    two  5  10
# 6  foo    one  6  12
# 7  foo  three  7  14

print(df.loc[df['A'] == 'foo'])

daje

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Jeśli masz wiele wartości, które chcesz uwzględnić, umieść je na liście (lub bardziej ogólnie, dowolne iterowalne) i użyj isin:

print(df.loc[df['B'].isin(['one','three'])])

daje

     A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Pamiętaj jednak, że jeśli chcesz to zrobić wiele razy, bardziej efektywne jest najpierw utworzenie indeksu, a następnie użycie df.loc:

df = df.set_index(['B'])
print(df.loc['one'])

daje

       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12

lub, aby dołączyć wiele wartości z indeksu, użyj df.index.isin:

df.loc[df.index.isin(['one','two'])]

daje

       A  C   D
B              
one  foo  0   0
one  bar  1   2
two  foo  2   4
two  foo  4   8
two  bar  5  10
one  foo  6  12
unutbu
źródło
19
W rzeczywistości df [df ['nazwa_kolumny]] == jakaś_wartość] również działa. Ale moja pierwsza próba, df.where (df ['colume_name'] == some_value) nie działa ... nie jestem pewien, dlaczego ...
szli
13
Podczas używania df.where(condition)warunek musi mieć taki sam kształt jak df.
unutbu
8
FYI: Jeśli chcesz wybrać wiersz na podstawie dwóch (lub więcej) etykiet (wymagających obu lub obu), zobacz stackoverflow.com/questions/31756340/...
Shane
7
Skoro df[df['column_name'] == some_value]działa, dlaczego potrzebujemy .loctutaj dodać ?
qqqwww,
311

Istnieje kilka sposobów wybierania wierszy z ramki danych pand:

  1. Indeksowanie boolowskie ( df[df['col'] == value])
  2. Indeksowanie pozycyjne ( df.iloc[...])
  3. Indeksowanie etykiet ( df.xs(...))
  4. df.query(...) API

Poniżej pokazuję przykłady każdego z nich wraz z radą, kiedy stosować określone techniki. Załóżmy, że naszym kryterium jest kolumna 'A'=='foo'

(Uwaga na temat wydajności: w przypadku każdego typu podstawowego możemy uprościć sprawę, używając interfejsu API pand lub możemy wyjść poza interfejs API, zwykle w celu numpyprzyspieszenia.)


Konfiguracja
Pierwszą rzeczą, której potrzebujemy, jest określenie warunku, który będzie naszym kryterium wyboru wierszy. Zaczniemy od przypadku OP column_name == some_valuei dołączymy kilka innych typowych przypadków użycia.

Pożyczanie od @unutbu:

import pandas as pd, numpy as np

df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})

1. Indeksowanie boolowskie

... Indeksowanie boolowskie wymaga znalezienia prawdziwej wartości 'A'kolumny każdego wiersza równej 'foo', a następnie użycia tych wartości prawdy do zidentyfikowania, które wiersze zachować. Zazwyczaj chcielibyśmy nazwać tej serii tablicę wartości prawdę mask. Zrobimy to również tutaj.

mask = df['A'] == 'foo'

Następnie możemy użyć tej maski do wycinania lub indeksowania ramki danych

df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Jest to jeden z najprostszych sposobów wykonania tego zadania, a jeśli wydajność lub intuicyjność nie stanowią problemu, powinna to być wybrana metoda. Jeśli jednak wydajność stanowi problem, warto rozważyć alternatywny sposób utworzenia pliku mask.


2. Indeksowanie pozycji

Indeksowanie pozycyjne ( df.iloc[...]) ma swoje przypadki użycia, ale nie jest to jeden z nich. Aby określić, gdzie należy kroić, najpierw musimy wykonać tę samą analizę boolowską, którą wykonaliśmy powyżej. To pozostawia nam jeden dodatkowy krok do wykonania tego samego zadania.

mask = df['A'] == 'foo'
pos = np.flatnonzero(mask)
df.iloc[pos]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

3. Indeksowanie etykiet

Indeksowanie etykiet może być bardzo przydatne, ale w tym przypadku ponownie wykonujemy więcej pracy bez żadnych korzyści

df.set_index('A', append=True, drop=False).xs('foo', level=1)

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

4. df.query()API

pd.DataFrame.queryjest bardzo eleganckim / intuicyjnym sposobem wykonania tego zadania, ale często jest wolniejszy. Jednakże , jeśli zwrócić uwagę na czasy poniżej, dla dużych danych, zapytanie jest bardzo wydajny. Bardziej niż standardowe podejście i podobnej wielkości jak moja najlepsza sugestia.

df.query('A == "foo"')

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Preferuję używanie Boolean mask

Rzeczywistych ulepszeń można dokonać, modyfikując sposób, w jaki tworzymy nasze Boolean mask.

maskalternatywa 1
Użyj podstawowej numpytablicy i zrezygnuj z narzutów związanych z tworzeniem kolejnejpd.Series

mask = df['A'].values == 'foo'

Na końcu pokażę pełniejsze testy czasowe, ale spójrzmy tylko na wzrost wydajności, jaki uzyskujemy dzięki przykładowej ramce danych. Najpierw przyjrzymy się różnicy w tworzeniumask

%timeit mask = df['A'].values == 'foo'
%timeit mask = df['A'] == 'foo'

5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Ocena za maskpomocą numpytablicy jest ~ 30 razy szybsza. Wynika to częściowo z tego, że numpyocena jest często szybsza. Wynika to również częściowo z braku narzutu niezbędnego do zbudowania indeksu i odpowiedniego pd.Seriesobiektu.

Następnie przyjrzymy się terminowi krojenia z jednym maskna drugi.

mask = df['A'].values == 'foo'
%timeit df[mask]
mask = df['A'] == 'foo'
%timeit df[mask]

219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Wzrost wydajności nie jest tak wyraźny. Zobaczymy, czy to wytrzyma bardziej szczegółowe testy.


maskalternatywa 2
Mogliśmy również zrekonstruować ramkę danych. Podczas odtwarzania ramki danych istnieje duże zastrzeżenie - musisz się tym zająćdtypes to zrobić!

Zamiast tego df[mask]to zrobimy

pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

Jeśli ramka danych jest typu mieszanego, jak w naszym przykładzie, to kiedy otrzymamy df.valueswynikową tablicę, będzie ona dtype objectzawierała wszystkie kolumny nowej ramki danych dtype object. Wymaga to astype(df.dtypes)i zabija wszelkie potencjalne przyrosty wydajności.

%timeit df[m]
%timeit pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

216 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.43 ms ± 39.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Jeśli jednak ramka danych nie jest typu mieszanego, jest to bardzo przydatny sposób na zrobienie tego.

Dany

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

d1

   A  B  C  D  E
0  0  2  7  3  8
1  7  0  6  8  6
2  0  2  0  4  9
3  7  3  2  4  3
4  3  6  7  7  4
5  5  3  7  5  9
6  8  7  6  4  7
7  6  2  6  6  5
8  2  8  7  5  8
9  4  7  6  1  5    

%%timeit
mask = d1['A'].values == 7
d1[mask]

179 µs ± 8.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Przeciw

%%timeit
mask = d1['A'].values == 7
pd.DataFrame(d1.values[mask], d1.index[mask], d1.columns)

87 µs ± 5.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Skróciliśmy czas o połowę.


maskalternatywa 3
@unutbu pokazuje również, jak używać pd.Series.isindo rozliczania każdego elementu df['A']znajdującego się w zbiorze wartości. To ocenia to samo, jeśli nasz zestaw wartości jest zbiorem jednej wartości, a mianowicie 'foo'. Ale uogólnia również, aby w razie potrzeby uwzględnić większe zestawy wartości. Okazuje się, że wciąż jest to dość szybkie, mimo że jest to bardziej ogólne rozwiązanie. Jedyną prawdziwą stratą jest intuicyjność dla tych, którzy nie znają tej koncepcji.

mask = df['A'].isin(['foo'])
df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Jednak, jak poprzednio, możemy wykorzystać numpydo poprawy wydajności, poświęcając praktycznie nic. Użyjemynp.in1d

mask = np.in1d(df['A'].values, ['foo'])
df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Czas
uwzględnię również inne pojęcia wymienione w innych postach w celach informacyjnych.
Kod poniżej

Każda kolumna w tej tabeli reprezentuje ramkę danych o innej długości, w której testujemy każdą funkcję. Każda kolumna pokazuje względny czas, przy czym najszybsza funkcja ma indeks bazowy wynoszący 1.0.

res.div(res.min())

                         10        30        100       300       1000      3000      10000     30000
mask_standard         2.156872  1.850663  2.034149  2.166312  2.164541  3.090372  2.981326  3.131151
mask_standard_loc     1.879035  1.782366  1.988823  2.338112  2.361391  3.036131  2.998112  2.990103
mask_with_values      1.010166  1.000000  1.005113  1.026363  1.028698  1.293741  1.007824  1.016919
mask_with_values_loc  1.196843  1.300228  1.000000  1.000000  1.038989  1.219233  1.037020  1.000000
query                 4.997304  4.765554  5.934096  4.500559  2.997924  2.397013  1.680447  1.398190
xs_label              4.124597  4.272363  5.596152  4.295331  4.676591  5.710680  6.032809  8.950255
mask_with_isin        1.674055  1.679935  1.847972  1.724183  1.345111  1.405231  1.253554  1.264760
mask_with_in1d        1.000000  1.083807  1.220493  1.101929  1.000000  1.000000  1.000000  1.144175

Zauważysz, że najszybsze czasy wydają się być dzielone między mask_with_valuesimask_with_in1d

res.T.plot(loglog=True)

wprowadź opis zdjęcia tutaj

Funkcje

def mask_standard(df):
    mask = df['A'] == 'foo'
    return df[mask]

def mask_standard_loc(df):
    mask = df['A'] == 'foo'
    return df.loc[mask]

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_values_loc(df):
    mask = df['A'].values == 'foo'
    return df.loc[mask]

def query(df):
    return df.query('A == "foo"')

def xs_label(df):
    return df.set_index('A', append=True, drop=False).xs('foo', level=-1)

def mask_with_isin(df):
    mask = df['A'].isin(['foo'])
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

Testowanie

res = pd.DataFrame(
    index=[
        'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc',
        'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d'
    ],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

for j in res.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in res.index:a
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        res.at[i, j] = timeit(stmt, setp, number=50)

Specjalny czas
Patrząc na szczególny przypadek, gdy mamy pojedynczy obiekt niebędący obiektem dtypedla całej ramki danych. Kod poniżej

spec.div(spec.min())

                     10        30        100       300       1000      3000      10000     30000
mask_with_values  1.009030  1.000000  1.194276  1.000000  1.236892  1.095343  1.000000  1.000000
mask_with_in1d    1.104638  1.094524  1.156930  1.072094  1.000000  1.000000  1.040043  1.027100
reconstruct       1.000000  1.142838  1.000000  1.355440  1.650270  2.222181  2.294913  3.406735

Okazuje się, że odbudowa nie jest warta kilkuset rzędów.

spec.T.plot(loglog=True)

wprowadź opis zdjęcia tutaj

Funkcje

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

def reconstruct(df):
    v = df.values
    mask = np.in1d(df['A'].values, ['foo'])
    return pd.DataFrame(v[mask], df.index[mask], df.columns)

spec = pd.DataFrame(
    index=['mask_with_values', 'mask_with_in1d', 'reconstruct'],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

Testowanie

for j in spec.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in spec.index:
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        spec.at[i, j] = timeit(stmt, setp, number=50)
piRSquared
źródło
6
Fantastyczna odpowiedź! 2 pytania, i) jak by to .iloc(numpy.where(..))porównać w tym schemacie? ii) czy spodziewałbyś się, że rankingi będą takie same, jeśli zastosujesz wiele warunków?
posdef
3
Do wykonania pd.Series.isin, trzeba pamiętać, że nie stosowanie np.in1dpod maską w konkretnym scenariuszu, Khash zastosowania w innych, a pośrednio stosuje kompromis między kosztem mieszaja kontra wydajności w konkretnych sytuacjach. Ta odpowiedź ma więcej szczegółów.
jpp
1
Przy 9 screenach jest to przeciążenie dla nowego lub nawet pośredniego użytkownika. Możesz i powinieneś sam podsumować tl; dr w pierwszym akapicie.
smci
@piRSquared Skalowanie ważne byś nic przeciwko @piRSquared, aby również zamieścić swoje doświadczenia na temat tego, jak dobrze rzeczywistych [{P|EXP}TIME] - a [{C|P|EXP}SPACE]- koszty korzystania z wyżej proponowanych form blokowo składni (top-down przetwarzanie całych dataframes naraz) rosną , a mianowicie, gdy skalowane do niektórych ~1E6, ~1E9, ~1E12liczb wierszy? Dzięki za pokazanie nam całego zdjęcia, Sir. Ilościowe odczyty wzorcowe z [min, Avg, MAX, StDev]są zawsze mile widziane, ponieważ zarówno wartości , jak mini MAXwartości towarzyszą Mean/StDevzwolnieniu partii.
user3666197,
Doskonała odpowiedź! Zapytanie rozwiązało mój problem!
Pavlos Ponos
280

tl; dr

Pandy równoważne

select * from table where column_name = some_value

jest

table[table.column_name == some_value]

Wiele warunków:

table[(table.column_name == some_value) | (table.column_name2 == some_value2)]

lub

table.query('column_name == some_value | column_name2 == some_value2')

Przykład kodu

import pandas as pd

# Create data set
d = {'foo':[100, 111, 222], 
     'bar':[333, 444, 555]}
df = pd.DataFrame(d)

# Full dataframe:
df

# Shows:
#    bar   foo 
# 0  333   100
# 1  444   111
# 2  555   222

# Output only the row(s) in df where foo is 222:
df[df.foo == 222]

# Shows:
#    bar  foo
# 2  555  222

W powyższym kodzie jest to wiersz, df[df.foo == 222]który podaje wiersze na podstawie wartości kolumny, 222w tym przypadku.

Możliwe są również różne warunki:

df[(df.foo == 222) | (df.bar == 444)]
#    bar  foo
# 1  444  111
# 2  555  222

Ale w tym momencie zaleciłbym użycie funkcji zapytania , ponieważ jest mniej gadatliwa i daje ten sam wynik:

df.query('foo == 222 | bar == 444')
imolit
źródło
5
queryto jedyna odpowiedź tutaj zgodna z łańcuchem metod. Wygląda na to, że to pandy analogiczne do filterdplyr.
Berk U.
3
Cześć, w trzecim przykładzie (wiele kolumn) Myślę, że potrzebujesz nawiasów kwadratowych, a [nie okrągłych (na zewnątrz.
user2739472
2
na początku myślałem, że |to dla AND, ale oczywiście jest to operator OR ...
O-9
dla wielu warunków przy użyciu AND, można to zrobićdf[condition1][condition2]
Ritwik
1
Pozostawiając to tutaj na wypadek, gdy jest to przydatne dla kogoś: z kwerendy 0.25 można używać nazw kolumn zawierających spacje w nazwie, umieszczając ją w backticksach:df.query('`my col` == 124')
cs95
65

Uważam, że składnia poprzednich odpowiedzi jest zbędna i trudna do zapamiętania. Pandas wprowadził tę query()metodę w wersji 0.13 i zdecydowanie wolę ją. Na twoje pytanie możesz to zrobićdf.query('col == val')

Reprodukcja z http://pandas.pydata.org/pandas-docs/version/0.17.0/indexing.html#indexing-query

In [167]: n = 10

In [168]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))

In [169]: df
Out[169]: 
          a         b         c
0  0.687704  0.582314  0.281645
1  0.250846  0.610021  0.420121
2  0.624328  0.401816  0.932146
3  0.011763  0.022921  0.244186
4  0.590198  0.325680  0.890392
5  0.598892  0.296424  0.007312
6  0.634625  0.803069  0.123872
7  0.924168  0.325076  0.303746
8  0.116822  0.364564  0.454607
9  0.986142  0.751953  0.561512

# pure python
In [170]: df[(df.a < df.b) & (df.b < df.c)]
Out[170]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

# query
In [171]: df.query('(a < b) & (b < c)')
Out[171]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

Możesz również uzyskać dostęp do zmiennych w środowisku, przygotowując plik @.

exclude = ('red', 'orange')
df.query('color not in @exclude')
Fredcallaway
źródło
1
Potrzebujesz tylko numexprzainstalowanego pakietu .
MERose
4
W moim przypadku potrzebowałem cytatu, ponieważ val jest łańcuchem. df.query ('col == "val"')
smerlung
28

Większa elastyczność .querydzięki pandas >= 0.25.0:

Zaktualizowana odpowiedź z sierpnia 2019 r

Ponieważ pandas >= 0.25.0możemy użyć tej querymetody do filtrowania ramek danych za pomocą metod pand, a nawet nazw kolumn zawierających spacje. Normalnie spacje w nazwach kolumn dawałyby błąd, ale teraz możemy to rozwiązać za pomocą backsticka (`) patrz GitHub :

# Example dataframe
df = pd.DataFrame({'Sender email':['[email protected]', "[email protected]", "[email protected]"]})

     Sender email
0  ex@example.com
1  reply@shop.com
2    buy@shop.com

Za .querypomocą metody str.endswith:

df.query('`Sender email`.str.endswith("@shop.com")')

Wynik

     Sender email
1  reply@shop.com
2    buy@shop.com

Możemy również użyć zmiennych lokalnych, poprzedzając je @w naszym zapytaniu:

domain = 'shop.com'
df.query('`Sender email`.str.endswith(@domain)')

Wynik

     Sender email
1  reply@shop.com
2    buy@shop.com
Erfan
źródło
26

Szybsze wyniki można osiągnąć za pomocą numpy.where .

Na przykład przy konfiguracji unubtu -

In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]: 
     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Porównanie czasowe:

In [68]: %timeit df.iloc[np.where(df.A.values=='foo')]  # fastest
1000 loops, best of 3: 380 µs per loop

In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop

In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop

In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop

In [74]: %timeit df.query('(A=="foo")')  # slowest
1000 loops, best of 3: 1.71 ms per loop
Shivsn
źródło
24

Oto prosty przykład

from pandas import DataFrame

# Create data set
d = {'Revenue':[100,111,222], 
     'Cost':[333,444,555]}
df = DataFrame(d)


# mask = Return True when the value in column "Revenue" is equal to 111
mask = df['Revenue'] == 111

print mask

# Result:
# 0    False
# 1     True
# 2    False
# Name: Revenue, dtype: bool


# Select * FROM df WHERE Revenue = 111
df[mask]

# Result:
#    Cost    Revenue
# 1  444     111
DataByDavid
źródło
17

Aby wybrać tylko określone kolumny z wielu kolumn dla danej wartości w pandach:

select col_name1, col_name2 from table where column_name = some_value.

Opcje:

df.loc[df['column_name'] == some_value][[col_name1, col_name2]]

lub

df.query['column_name' == 'some_value'][[col_name1, col_name2]]
SP001
źródło
16

Aby dołączyć do tego znanego pytania (choć trochę za późno): Możesz także zrobić df.groupby('column_name').get_group('column_desired_value').reset_index()nową ramkę danych z określoną kolumną o określonej wartości. Na przykład

import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split()})
print("Original dataframe:")
print(df)

b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1) 
#NOTE: the final drop is to remove the extra index column returned by groupby object
print('Sub dataframe where B is two:')
print(b_is_two_dataframe)

Uruchom to daje:

Original dataframe:
     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three
Sub dataframe where B is two:
     A    B
0  foo  two
1  foo  two
2  bar  two
TuanDT
źródło
Świetna odpowiedź. Chciałbym tylko dodać, że drugi (pd.DataFrame) jest zbędny, ponieważ get_group()automatycznie zwróci ramkę danych. Możesz także powiedzieć „drop = True” jako parametr parametru reset_index(). Innymi słowy, można go skrócić do: b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Mountain Scott
7

Możesz także użyć .apply:

df.apply(lambda row: row[df['B'].isin(['one','three'])])

W rzeczywistości działa wierszowo (tzn. Stosuje funkcję do każdego wiersza).

Dane wyjściowe to

   A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Wyniki są takie same jak przy użyciu, jak wspomniano w @unutbu

df[[df['B'].isin(['one','three'])]]
Vahidn
źródło