2016-01-25 14 views
5

Con un dato come questo (colonne, ma con 40e3) unoVectorized "e" per le colonne panda

import pandas as pd 
tcd = pd.DataFrame({ 
'a': {'p_1': 1, 'p_2': 1, 'p_3': 0, 'p_4': 0}, 
'b': {'p_1': 0, 'p_2': 1, 'p_3': 1, 'p_4': 1}, 
'c': {'p_1': 0, 'p_2': 0, 'p_3': 1, 'p_4': 0}}) 
tcd 
#  a b c 
# p_1 1 0 0 
# p_2 1 1 0 
# p_3 0 1 1 
# p_4 0 1 0 

cerco un modo vettorializzare per mettere il booleano e in una serie risultato :

a & b = ab -> 1 or True a & c = ac -> 0 or False 
1 0 0     1 0 0 
1 1 0     1 0 0 
0 1 1     0 1 0 
0 1 0     0 0 0 

per ora ho solo una soluzione brutta con un ciclo for ::

res = pd.Series(index=['a&a', 'a&b', 'a&c']) 
for i in range(3): 
    res[i] = (tcd.iloc[:, 0] & tcd.iloc[:, i]).any() 

res 
aa 1 
ab 1 
ac 0 

con il B.M. Rispondo ottengo questo

def get_shared_p(tcd, i): 
    res = (tcd.iloc[:, i][:, None] & tcd).any() 
    res.index += '&_{}'.format(i) 
    return res 

res = pd.DataFrame(columns=range(cols), index=range(cols)) 
for col_i in range(cols): 
    res.iloc[:, col_i] = list(get_shared_p(tcd, col_i)) 

print res 
#  0  1  2 
# 0 True True False 
# 1 True True True 
# 2 False True True 

Possiamo probabilmente evitare questo nuovo per ciclo.

risposta

3

Usa [:,None] per allineare i dati e la forza di trasmissione:

In[1] : res=(tcd.a[:,None] & tcd).any(); res.index+='&a'; res 

Out[1]: 
a&a  True 
b&a  True 
c&a False 
dtype: bool 
+0

davvero grandioso @ b-m! BTW possiamo usare lo stesso metodo per ottenere la matrice incrociata con & a, & b, & c o con & _0, & _1, & 2 – user3313834

+0

IIUC, 'res = (tcd.T.p_1 [:, None] & tcd.T) .any (); res.index + = '&p_1'; res'? –

+0

B.M. Ho aggiornato la domanda per spiegarlo – user3313834

4

È possibile utilizzare np.logical_and e numpy's broadcasting.

Dire si definisce x e y come prima colonna, e intera matrice, rispettivamente:

import numpy as np 

x = tcd.as_matrix() 
y = tcd.a.values.reshape((len(tcd), 1)) 

ora, utilizzando la trasmissione, trovare la logica e di x e y, e metterlo in and_:

and_ = np.logical_and(x, y) 

Infine, trovare se una qualsiasi delle righe in una delle colonne è vera:

>>> np.sum(and_) > 0 
array([ True, True, False], dtype=bool) 
1

vorrei risolvere questo problema in questo modo:

import pandas as pd 
import numpy as np 
from itertools import combinations 

tcd = pd.DataFrame({ 
'a': {'p_1': 1, 'p_2': 1, 'p_3': 0, 'p_4': 0}, 
'b': {'p_1': 0, 'p_2': 1, 'p_3': 1, 'p_4': 1}, 
'c': {'p_1': 0, 'p_2': 0, 'p_3': 1, 'p_4': 0}}) 

for c in combinations(tcd.columns, 2): 
    tcd[c[0]+c[1]] = np.logical_and(tcd[c[0]], tcd[c[1]]) 

print(cd) 

Con uscita:

 a b c  ab  ac  bc 
p_1 1 0 0 False False False 
p_2 1 1 0 True False False 
p_3 0 1 1 False False True 
p_4 0 1 0 False False False 
+0

devo dire , sembra che sarà molto lento. –

Problemi correlati