2016-04-05 12 views
5

Ho un pandas.DataFrame della formaclassificare i dati per valore in panda

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

Ho un molto lungapandas.Series della forma:

value 
5.7 
30.4 
21 
35.1 

voglio dare a ciascun valore di la serie il suo nome corrispondente rispetto al nome_fondo low_bound/high_bound/name. Ecco il mio risultato atteso:

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

Infatti, 5,7 nome è 'un' dal 5,7 è compreso tra 0 e 10 esclusi.

Quale sarebbe il codice più efficiente? So di poter risolvere il problema scorrendo attraverso la serie, ma forse c'è una soluzione vettoriale più veloce che mi sfugge.

Nota infine che i miei limiti possono essere personalizzati e irregolari. Qui sono regolari per il bene dell'esempio.

risposta

4

Panda ha un metodo chiamato cut che farà ciò che si vuole:

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"]) 

Che vi darà il seguente, che è quindi possibile rimettere in qualche dataframe o comunque si vuole tenere i tuoi dati:

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

A seconda di come sono irregolari i cassetti (e cosa si intende esattamente per abitudine/irregolare), potrebbe essere necessario ricorrere alla ripetizione della serie. Non riesco a pensare alla parte superiore della mia testa di un builtin che gestirà questo per voi, soprattutto dato che dipende dal grado/tipo di irregolarità nei cassonetti.

Looping saggio, questo metodo funzionerà se si dispone di un limite inferiore e superiore, a prescindere dalla "regolarità":

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

mi rendo conto che non si potrebbe desiderare per scorrere una serie enorme, ma almeno non stiamo indicizzando manualmente nel dataframe, il che probabilmente renderebbe le cose ancora più lente

Problemi correlati