2016-04-05 5 views
5

Mam pandas.DataFrame formularzaKlasyfikować dane wg wartości w pand

low_bound high_bound name 
0   10   'a' 
10   20   'b' 
20   30   'c' 
30   40   'd' 
40   50   'e' 

mam bardzo długopandas.Series formularza:

value 
5.7 
30.4 
21 
35.1 

chcę dać do każdej wartości Serii odpowiadającej jej nazwie w odniesieniu do zmiennej DataFrame low_bound/high_bound/name. Oto mój oczekiwany wynik:

value   name 
5.7   'a' 
30.4   'd' 
21   'c' 
35.1   'd' 

Rzeczywiście, 5.7 nazwa jest 'a' od 5.7 jest między 0 i 10 wyłączonych.

Jaki byłby najbardziej wydajny kod? Wiem, że mogę rozwiązać problem, powtarzając serię, ale być może istnieje szybsze, wektorowe rozwiązanie, które mi ucieka.

Pamiętaj, że moje granice mogą być niestandardowe i nieregularne. Tutaj są one regularne ze względu na przykład.

Odpowiedz

4

Pandy ma metodę zwaną cut że będą robić to, co chcesz:

import pandas as pd 

data = [{"low": 0, "high": 10, "name": "a"}, 
     {"low": 10, "high": 20, "name": "b"}, 
     {"low": 20, "high": 30, "name": "c"}, 
     {"low": 30, "high": 40, "name": "d"}, 
     {"low": 40, "high": 50, "name": "e"},] 

myDF = pd.DataFrame(data) 

#data to be binned 
mySeries = pd.Series([5.7, 30.4, 21, 35.1]) 

#create bins from original data 
bins = list(myDF["high"]) 
bins.insert(0,0) 

print pd.cut(mySeries, bins, labels = myDF["name"]) 

To daje następujące dane, które można następnie umieścić z powrotem do jakiegoś dataframe czy jakkolwiek chcesz trzymać swoje dane:

0 a 
1 d 
2 c 
3 d 
dtype: category 
Categories (5, object): [a < b < c < d < e] 

W zależności od tego, jak nieregularne są twoje pojemniki (i co masz na myśli dokładnie według niestandardowych/nieregularnych), być może będziesz musiał uciekać się do zapętlenia serii. Nie mogę myśleć z góry o wbudowanym, który sobie z tym poradzi, zwłaszcza, że ​​zależy to od stopnia/rodzaju nieprawidłowości w pojemnikach.

Pętla mądry, ta metoda będzie działać, jeśli masz dolną i górną granicę, niezależnie od „prawidłowości”:

for el in mySeries: 
    print myDF["name"][(myDF["low"] < el) & (myDF["high"] > el)] 

Rozumiem, że możesz nie chcieć pętli ogromnej serii, ale przynajmniej nie dokonujemy ręcznego indeksowania w ramce danych, co prawdopodobnie spowodowałoby jeszcze wolniejszą pracę.