2013-03-09 18 views
106

Na przykład mam proste DF:Wybór złożonych kryteriów z pandas.DataFrame

import pandas as pd 
from random import randint 

df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)], 
        'B': [randint(1, 9)*10 for x in xrange(10)], 
        'C': [randint(1, 9)*100 for x in xrange(10)]}) 

mogę wybrać wartości od „A”, za które odpowiada wartości „B” będzie większa niż 50, a dla ' C '- nie równe 900, używając metod i idiomów Pandy?

+0

Głosuj na swoje imię! – 8090PZ

Odpowiedz

196

Pewnie! Setup:

>>> import pandas as pd 
>>> from random import randint 
>>> df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)], 
        'B': [randint(1, 9)*10 for x in xrange(10)], 
        'C': [randint(1, 9)*100 for x in xrange(10)]}) 
>>> df 
    A B C 
0 9 40 300 
1 9 70 700 
2 5 70 900 
3 8 80 900 
4 7 50 200 
5 9 30 900 
6 2 80 700 
7 2 80 400 
8 5 80 300 
9 7 70 800 

Możemy zastosować operacje kolumn i uzyskać logicznych obiektów Seria:

>>> df["B"] > 50 
0 False 
1  True 
2  True 
3  True 
4 False 
5 False 
6  True 
7  True 
8  True 
9  True 
Name: B 
>>> (df["B"] > 50) & (df["C"] == 900) 
0 False 
1 False 
2  True 
3  True 
4 False 
5 False 
6 False 
7 False 
8 False 
9 False 

[Update, aby przełączyć się do nowego stylu .loc]:

A potem możemy wykorzystać do indeks do obiektu. Wskaźniki dla dostępu odczytu, możesz połączyć:

>>> df["A"][(df["B"] > 50) & (df["C"] == 900)] 
2 5 
3 8 
Name: A, dtype: int64 

ale można dostać się w kłopoty z powodu różnicy między myślą i kopię w ten sposób dostęp do zapisu. Można użyć .loc zamiast:

>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] 
2 5 
3 8 
Name: A, dtype: int64 
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"].values 
array([5, 8], dtype=int64) 
>>> df.loc[(df["B"] > 50) & (df["C"] == 900), "A"] *= 1000 
>>> df 
     A B C 
0  9 40 300 
1  9 70 700 
2 5000 70 900 
3 8000 80 900 
4  7 50 200 
5  9 30 900 
6  2 80 700 
7  2 80 400 
8  5 80 300 
9  7 70 800 

pamiętać, że przypadkowo zrobił == 900 a nie != 900 lub ~(df["C"] == 900), ale jestem zbyt leniwy, aby go naprawić. Ćwiczenie dla czytelnika. : ^)

+0

Znakomity! Wielkie dzięki! –

+4

Jak zastąpić (zaktualizować) wiersze otrzymane przez wybór? –

+0

Aktualizacja ".loc" - dobrze by było, gdybyś wyjaśnił, skąd otrzymujemy kopię i gdzie znajduje się widok. –

10

Innym rozwiązaniem jest użycie metody query:

import pandas as pd 

from random import randint 
df = pd.DataFrame({'A': [randint(1, 9) for x in xrange(10)], 
        'B': [randint(1, 9) * 10 for x in xrange(10)], 
        'C': [randint(1, 9) * 100 for x in xrange(10)]}) 
print df 

    A B C 
0 7 20 300 
1 7 80 700 
2 4 90 100 
3 4 30 900 
4 7 80 200 
5 7 60 800 
6 3 80 900 
7 9 40 100 
8 6 40 100 
9 3 10 600 

print df.query('B > 50 and C != 900') 

    A B C 
1 7 80 700 
2 4 90 100 
4 7 80 200 
5 7 60 800 

Teraz, jeśli chcesz zmienić zwracanych wartości w kolumnie A można zaoszczędzić swój indeks:

my_query_index = df.query('B > 50 & C != 900').index 

.. .. i użyj .iloc, aby je zmienić, tj .:

df.iloc[my_query_index, 0] = 5000 

print df 

     A B C 
0  7 20 300 
1 5000 80 700 
2 5000 90 100 
3  4 30 900 
4 5000 80 200 
5 5000 60 800 
6  3 80 900 
7  9 40 100 
8  6 40 100 
9  3 10 600 
Powiązane problemy