Filtruj wiersze ramki danych, jeśli wartość w kolumnie znajduje się na ustawionej liście wartości [duplikat]

to pytanie ma już odpowiedzi tutaj : jak filtrować ramkę danych Pandy używając 'in' I 'not in' jak w SQL (8 odpowiedzi) Użyj listy wartości, aby wybrać wiersze z ramki danych Panda (1 ODPOWIEDŹ) Zamknięty 2 lata temu.

Mam Python pandas DataFrame rpt:

rpt
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 47518 entries, ('000002', '20120331') to ('603366', '20091231')
Data columns:
STK_ID                    47518  non-null values
STK_Name                  47518  non-null values
RPT_Date                  47518  non-null values
sales                     47518  non-null values

Mogę filtrować wiersze, których ID akcji to '600809' w następujący sposób: rpt[rpt['STK_ID'] == '600809']

<class 'pandas.core.frame.DataFrame'>
MultiIndex: 25 entries, ('600809', '20120331') to ('600809', '20060331')
Data columns:
STK_ID                    25  non-null values
STK_Name                  25  non-null values
RPT_Date                  25  non-null values
sales                     25  non-null values

I chcę Zbierz wszystkie rzędy niektórych zapasów razem, takie jak ['600809','600141','600329']. To znaczy, że chcę taką składnię:

stk_list = ['600809','600141','600329']

rst = rpt[rpt['STK_ID'] in stk_list] # this does not works in pandas 

Ponieważ pandy nie akceptują powyższego polecenia, jak osiągnąć cel?

Author: firelynx, 2012-08-22

7 answers

Użyj metody isin:

rpt[rpt['STK_ID'].isin(stk_list)]

 702
Author: BrenBarn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-25 00:45:48

isin() jest idealny, jeśli masz listę dokładnych dopasowań, ale jeśli masz listę częściowych dopasowań lub podłańcuchów do wyszukiwania, możesz filtrować za pomocą str.contains metody i wyrażenia regularne.

Na przykład, jeśli chcemy zwrócić ramkę danych, w której wszystkie identyfikatory stock rozpoczynają się od '600', a następnie są poprzedzone dowolnymi trzema cyframi:

>>> rpt[rpt['STK_ID'].str.contains(r'^600[0-9]{3}$')] # ^ means start of string
...   STK_ID   ...                                    # [0-9]{3} means any three digits
...  '600809'  ...                                    # $ means end of string
...  '600141'  ...
...  '600329'  ...
...      ...   ...

Załóżmy, że teraz mamy listę łańcuchów, na których chcemy, aby wartości w 'STK_ID' kończyły się, np.

endstrings = ['01$', '02$', '05$']

Możemy dołączyć te łańcuchy ze znakiem regex ' or ' | i przekazują łańcuch do str.contains, aby filtrować ramkę danych:

>>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)]
...   STK_ID   ...
...  '155905'  ...
...  '633101'  ...
...  '210302'  ...
...      ...   ...

Wreszcie, contains może ignorować wielkość liter (ustawiając case=False), co pozwala na bardziej ogólne określenie łańcuchów, które chcesz dopasować.

Na przykład,

str.contains('pandas', case=False)

Pasuje PANDAS, PanDAs, paNdAs123, i tak dalej.

 118
Author: Alex Riley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-12 18:29:27

Możesz również użyć zakresów używając:

b = df[(df['a'] > 1) & (df['a'] < 5)]
 44
Author: yemu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-10 12:26:29

Możesz również bezpośrednio zapytać swoją ramkę danych o te informacje.

rpt.query('STK_ID in (600809,600141,600329)')

Lub podobnie Szukaj zakresów:

rpt.query('60000 < STK_ID < 70000')
 42
Author: bscan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-27 15:39:51

Wycinanie danych za pomocą pand

Dane takie jak:

    RPT_Date  STK_ID STK_Name  sales
0 1980-01-01       0   Arthur      0
1 1980-01-02       1    Beate      4
2 1980-01-03       2    Cecil      2
3 1980-01-04       3     Dana      8
4 1980-01-05       4     Eric      4
5 1980-01-06       5    Fidel      5
6 1980-01-07       6   George      4
7 1980-01-08       7     Hans      7
8 1980-01-09       8   Ingrid      7
9 1980-01-10       9    Jones      4

Istnieje wiele sposobów wybierania lub krojenia danych.

Używanie .isin

Najbardziej oczywistą jest .isin funkcja. Możesz stworzyć maskę, która daje Ci serię True/False poleceń, które można zastosować do ramki danych takiej jak ta:

mask = df['STK_ID'].isin([4, 2, 6])

mask
0    False
1    False
2     True
3    False
4     True
5    False
6     True
7    False
8    False
9    False
Name: STK_ID, dtype: bool

df[mask]
    RPT_Date  STK_ID STK_Name  sales
2 1980-01-03       2    Cecil      2
4 1980-01-05       4     Eric      4
6 1980-01-07       6   George      4
Maskowanie jest doraźnym rozwiązaniem problemu, ale nie zawsze działa dobrze pod względem szybkości i pamięci.

Z indeksowanie

Ustawiając indeks na kolumnę STK_ID, możemy użyć pandy wbudowanej w obiekt krojenia .loc

df.set_index('STK_ID', inplace=True)
         RPT_Date STK_Name  sales
STK_ID                           
0      1980-01-01   Arthur      0
1      1980-01-02    Beate      4
2      1980-01-03    Cecil      2
3      1980-01-04     Dana      8
4      1980-01-05     Eric      4
5      1980-01-06    Fidel      5
6      1980-01-07   George      4
7      1980-01-08     Hans      7
8      1980-01-09   Ingrid      7
9      1980-01-10    Jones      4

df.loc[[4, 2, 6]]
         RPT_Date STK_Name  sales
STK_ID                           
4      1980-01-05     Eric      4
2      1980-01-03    Cecil      2
6      1980-01-07   George      4

Jest to szybki sposób na zrobienie tego, nawet jeśli indeksowanie może zająć trochę czasu, oszczędza to czas, jeśli chcesz wykonać wiele takich zapytań.

Scalanie ramek danych

Można to również zrobić poprzez scalanie ramek danych. Pasowałoby to bardziej do scenariusza, w którym masz o wiele więcej danych niż w tych przykładach.

stkid_df = pd.DataFrame({"STK_ID": [4,2,6]})
df.merge(stkid_df, on='STK_ID')
   STK_ID   RPT_Date STK_Name  sales
0       2 1980-01-03    Cecil      2
1       4 1980-01-05     Eric      4
2       6 1980-01-07   George      4

Uwaga

Wszystkie powyższe metody działają nawet jeśli istnieje wiele wierszy o tym samym 'STK_ID'

 29
Author: firelynx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Możesz również osiągnąć podobne wyniki za pomocą 'query' i@:

Eg:

df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']})
df = pd.DataFrame({'A' : [5,6,3,4], 'B' : [1,2,3, 5]})
list_of_values = [3,6]
result= df.query("A in @list_of_values")
result
   A  B
1  6  2
2  3  3
 11
Author: akuriako,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-28 03:04:39

Możesz użyć query, czyli:

b = df.query('a > 1 & a < 5')
 6
Author: Pedro Lobito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-26 20:09:12