2015-09-24 6 views
5

C'è un buon modo per trovare l'insieme degli indici di colonna per i valori diversi da zero in ogni riga nel frame dei dati dei panda? Devo attraversare il frame dei dati riga per fila?trovare il set di indici di colonna per valori diversi da zero in ogni riga nel frame dei dati dei panda

Ad esempio, il frame di dati è

c1 c2 c3 c4 c5 c6 c7 c8 c9 
1 1 0 0 0 0 0 0 0 
1 0 0 0 0 0 0 0 0 
0 1 0 0 0 0 0 0 0 
1 0 0 0 0 0 0 0 0 
0 1 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 
0 2 1 1 1 1 1 0 2 
1 5 5 0 0 1 0 4 6 
4 3 0 1 1 1 1 5 10 
3 5 2 4 1 2 2 1 3 
6 4 0 1 0 0 0 0 0 
3 9 1 0 1 0 2 1 0 

L'uscita è prevista per

['c1','c2'] 
['c1'] 
['c2'] 
... 

risposta

5

Sembra che devi attraversare il DataFrame per riga.

cols = df.columns 
bt = df.apply(lambda x: x > 0) 
bt.apply(lambda x: list(cols[x.values]), axis=1) 

e otterrete:

0         [c1, c2] 
1          [c1] 
2          [c2] 
3          [c1] 
4          [c2] 
5          [] 
6    [c2, c3, c4, c5, c6, c7, c9] 
7     [c1, c2, c3, c6, c8, c9] 
8   [c1, c2, c4, c5, c6, c7, c8, c9] 
9  [c1, c2, c3, c4, c5, c6, c7, c8, c9] 
10       [c1, c2, c4] 
11    [c1, c2, c3, c5, c7, c8] 
dtype: object 

Se le prestazioni sono la materia, cercare di passare raw=True alla creazione dataframe booleano come di seguito:

%timeit df.apply(lambda x: x > 0, raw=True).apply(lambda x: list(cols[x.values]), axis=1) 
1000 loops, best of 3: 812 µs per loop 

E ti porta una migliore guadagno di prestazioni. Di seguito è raw=False (che è di default) risultato:

%timeit df.apply(lambda x: x > 0).apply(lambda x: list(cols[x.values]), axis=1) 
100 loops, best of 3: 2.59 ms per loop 
1

Potenzialmente in una struttura dati (piuttosto che una serie di liste) è impilare:

In [11]: res = df[df!=0].stack() 

In [12]: res 
Out[12]: 
0 c1  1 
    c2  1 
1 c1  1 
2 c2  1 
3 c1  1 
... 

E si può scorrere sulle righe originali:

In [13]: res.loc[0] 
Out[13]: 
c1 1 
c2 1 
dtype: float64 

In [14]: res.loc[0].index 
Out[14]: Index(['c1', 'c2'], dtype='object') 

Nota: ho pensato che hai utilizzato per essere in grado di restituire un elenco in una applicazione (per creare un dataframe che ha elementi della lista) questo non è più sembra essere il caso.

2

Che ne dite di questo approccio?

#create a True/False data frame 
df_boolean = df>0 

#a little helper method that uses boolean slicing internally 
def bar(x,columns): 
    return ','.join(list(columns[x])) 

#use an apply along the column axis 
df_boolean['result'] = df_boolean.apply(lambda x: bar(x,df_boolean.columns),axis=1) 

# filter out the empty "rows" adn grab the result column 
df_result = df_boolean[df_boolean['result'] != '']['result'] 

#append an axis, just so each line will will output a list 
lst_result = df_result.values[:,np.newaxis] 

print '\n'.join([ str(myelement) for myelement in lst_result]) 

e questo produce:

['c1,c2'] 
['c1'] 
['c2'] 
['c1'] 
['c2'] 
['c2,c3,c4,c5,c6,c7,c9'] 
['c1,c2,c3,c6,c8,c9'] 
['c1,c2,c4,c5,c6,c7,c8,c9'] 
['c1,c2,c3,c4,c5,c6,c7,c8,c9'] 
['c1,c2,c4'] 
['c1,c2,c3,c5,c7,c8'] 
+0

Scari mi ha battuto sul tempo e con una soluzione più concisa. Posso lasciare la mia risposta online per dimostrare la scrittura dell'output o felice di rimuovere. – Dickster

Problemi correlati