2015-06-01 2 views
6

Chcę wybrać kilka określonych wierszy na podstawie wartości dwóch kolumn. Na przykład:Wybierz rzędy klatek pandy na podstawie wartości dwóch kolumn

d = {'user' : [1., 2., 3., 4] ,'item' : [5., 6., 7., 8.],'f1' : [9., 16., 17., 18.], 'f2':[4,5,6,5], 'f3':[4,5,5,8]} 
df = pd.DataFrame(d) 
print df 

Out: 
    f1 f2 f3 item user 
0 9 4 4  5  1 
1 16 5 5  6  2 
2 17 6 5  7  3 
3 18 5 8  8  4 

Chcę wybrać wiersze na podstawie wartości "użytkownika" i "elementu". Biorąc pod uwagę 2d numpy tablica przechowująca [user, poz] Wartości par:

samples = np.array([[1,5],[3,7],[3,7],[2,6]]) 
Out: 
array([[1, 5], 
     [3, 7], 
     [3, 7], 
     [2, 6]]) 

Następnie oczekiwany wynik to:

Out: 
    f1 f2 f3 item user 
0 9 4 4  5  1 
2 17 6 5  7  3 
2 17 6 5  7  3 
1 16 5 5  6  2 

Następnie mój ostatecznym celem jest uzyskanie 2d NumPy sklepów tablicy wszystko wartości kolumny z wyjątkiem pozycji i użytkownika, który jest:

Out: 
array([[9, 4, 4], 
     [17, 6, 5], 
     [17, 6, 5], 
     [16, 5, 5]]) 

Jak widzimy, to jest wartości kolumn F1, F2, F3.

Jak mogę to zrobić?

Odpowiedz

8

Jeśli się samples DataFrame z kolumnami user i item, wtedy można uzyskać żądane wartości z inner join. Domyślnie pd.merge łączy we wszystkich kolumnach wspólnych samples i df - w tym przypadku będzie to user i item. Stąd

result = pd.merge(samples, df, how='inner') 

daje

user item f1 f2 f3 
0  1  5 9 4 4 
1  3  7 17 6 5 
2  3  7 17 6 5 
3  2  6 16 5 5 

import numpy as np 
import pandas as pd 

d = {'user' : [1., 2., 3., 4] ,'item' : [5., 6., 7., 8.],'f1' : [9., 16., 17., 18.], 'f2':[4,5,6,5], 'f3':[4,5,5,8]} 
df = pd.DataFrame(d) 
samples = np.array([[1,5],[3,7],[3,7],[2,6]]) 
samples = pd.DataFrame(samples, columns=['user', 'item']) 

result = pd.merge(samples, df, how='inner') 
result = result[['f1', 'f2', 'f3']] 
result = result.values 
print(result) 

Plony

[[ 9. 4. 4.] 
[ 17. 6. 5.] 
[ 17. 6. 5.] 
[ 16. 5. 5.]] 
+0

Wow! @unutbu, to świetnie! Dzięki! Właśnie tego chcę, ponieważ nie chcę używać pętli. – Excalibur

1

Jedno podejście, które jest nieco nachylone numpy Tablica -

import numpy as np 

# Convert item and user columns to a 2-column array 
item_user_arr = np.asarray(df[["item","user"]]).astype(int) 

# Mask of matches across rows of samples and item_user_arr, with columns flipped 
mask = (samples[:,None,1]==item_user_arr[:,0]) & (samples[:,None,0]==item_user_arr[:,1]) 

# Get indices of matches 
_,C = np.where(mask) 

# Use those indices to select data from f1,f2,f3 columns for final output array 
out = np.asarray(df[["f1","f2","f3"]])[C,:] 

wyjściowe dla poszczególnych wejść -

In [536]: out 
Out[536]: 
array([[ 9., 4., 4.], 
     [ 17., 6., 5.], 
     [ 17., 6., 5.], 
     [ 16., 5., 5.]]) 
+0

Dzięki @Divakar, jest to również doskonały sposób na rozwiązanie tego problemu! – Excalibur