For eksempel har jeg enkel DF:
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)]})
Kan jeg velge verdier fra 'A' for hvilke tilsvarende verdier for 'B' vil være større enn 50, og for 'C' - ikke lik 900, ved hjelp av metoder og uttrykk for Pandas?
Klart! Oppsett:
>>> import pandas as pd
>>> from random import randint
>>> df = pd.DataFrame({'A': [randint(1, 9) for x in range(10)],
'B': [randint(1, 9)*10 for x in range(10)],
'C': [randint(1, 9)*100 for x in range(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
Vi kan bruke kolonneoperasjoner og få boolske serieobjekter:
>>> 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
[Oppdater, for å bytte til ny stil .loc
]:
Og så kan vi bruke disse til å indeksere inn i objektet. For lesetilgang kan du kjede indekser:
>>> df["A"][(df["B"] > 50) & (df["C"] == 900)]
2 5
3 8
Name: A, dtype: int64
men du kan få deg selv i trøbbel på grunn av forskjellen mellom en visning og en kopi som gjør dette for skrivetilgang. Du kan bruke .loc
i stedet:
>>> 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
Legg merke til at jeg ved et uhell skrev == 900
og ikke != 900
, eller ~(df["C"] == 900)
, men jeg er for lat til å fikse det. Øvelse for leseren :^)
En annen løsning er å bruke query-metoden:
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
Hvis du nå vil endre de returnerte verdiene i kolonne A, kan du lagre indeksen deres:
my_query_index = df.query('B > 50 & C != 900').index
.... og bruke .iloc
for å endre dem, dvs:
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
Du kan bruke pandaer det har noen innebygde funksjoner for sammenligning. Så hvis du vil velge verdier av "A" som er oppfylt av betingelsene for "B" og "C" (forutsatt at du vil ha tilbake et DataFrame pandas-objekt)
df[['A']][df.B.gt(50) & df.C.ne(900)]
df[['A']]
vil gi deg tilbake kolonne A i DataFrame-format.
pandas 'gt' -funksjonen vil returnere posisjonene i kolonne B som er større enn 50 og 'ne' vil returnere posisjonene som ikke er lik 900.