¿Cómo contar valores no NaN a través de columnas en el dataframe de pandas?

Mis datos se ven así:

Close abcde Time 2015-12-03 2051.25 5 4 3 1 1 05:00:00 2015-12-04 2088.25 5 4 3 1 NaN 06:00:00 2015-12-07 2081.50 5 4 3 NaN NaN 07:00:00 2015-12-08 2058.25 5 4 NaN NaN NaN 08:00:00 2015-12-09 2042.25 5 NaN NaN NaN NaN 09:00:00 

Necesito contar ‘horizontalmente’ los valores en las columnas [‘a’] a [‘e’] que no son NaN. Entonces el resultado sería este:

 df['Count'] = ..... df Close abcde Time Count 2015-12-03 2051.25 5 4 3 1 1 05:00:00 5 2015-12-04 2088.25 5 4 3 1 NaN 06:00:00 4 2015-12-07 2081.50 5 4 3 NaN NaN 07:00:00 3 2015-12-08 2058.25 5 4 NaN NaN NaN 08:00:00 2 2015-12-09 2042.25 5 NaN NaN NaN NaN 09:00:00 1 

Gracias

Puede subseleccionar desde su df y el count llamadas que pasa el axis=1 :

 In [24]: df['count'] = df[list('abcde')].count(axis=1) df Out[24]: Close abcde Time count 2015-12-03 2051.25 5 4 3 1 1 05:00:00 5 2015-12-04 2088.25 5 4 3 1 NaN 06:00:00 4 2015-12-07 2081.50 5 4 3 NaN NaN 07:00:00 3 2015-12-08 2058.25 5 4 NaN NaN NaN 08:00:00 2 2015-12-09 2042.25 5 NaN NaN NaN NaN 09:00:00 1 

Tiempos

 In [25]: %timeit df[['a', 'b', 'c', 'd', 'e']].apply(lambda x: sum(x.notnull()), axis=1) %timeit df.drop(['Close', 'Time'], axis=1).count(axis=1) %timeit df[list('abcde')].count(axis=1) 100 loops, best of 3: 3.28 ms per loop 100 loops, best of 3: 2.76 ms per loop 100 loops, best of 3: 2.98 ms per loop 

apply es el más lento, lo que no es una sorpresa, la versión drop es un poco más rápida pero semánticamente prefiero pasar la lista de intereses y el count llamadas para facilitar la lectura

Hmm sigo teniendo diferentes tiempos ahora:

 In [27]: %timeit df[['a', 'b', 'c', 'd', 'e']].apply(lambda x: sum(x.notnull()), axis=1) %timeit df.drop(['Close', 'Time'], axis=1).count(axis=1) %timeit df[list('abcde')].count(axis=1) %timeit df[['a', 'b', 'c', 'd', 'e']].count(axis=1) 100 loops, best of 3: 3.33 ms per loop 100 loops, best of 3: 2.7 ms per loop 100 loops, best of 3: 2.7 ms per loop 100 loops, best of 3: 2.57 ms per loop 

Más horas

 In [160]: %timeit df[['a', 'b', 'c', 'd', 'e']].apply(lambda x: sum(x.notnull()), axis=1) %timeit df.drop(['Close', 'Time'], axis=1).count(axis=1) %timeit df[list('abcde')].count(axis=1) %timeit df[['a', 'b', 'c', 'd', 'e']].count(axis=1) %timeit df[list('abcde')].notnull().sum(axis=1) 1000 loops, best of 3: 1.4 ms per loop 1000 loops, best of 3: 1.14 ms per loop 1000 loops, best of 3: 1.11 ms per loop 1000 loops, best of 3: 1.11 ms per loop 1000 loops, best of 3: 1.05 ms per loop 

Parece que las pruebas para notnull y notnull (como notnull producirá una máscara booleana) son más rápidas en este conjunto de datos

En una fila de 50k df el último método es un poco más rápido:

 In [172]: %timeit df[['a', 'b', 'c', 'd', 'e']].apply(lambda x: sum(x.notnull()), axis=1) %timeit df.drop(['Close', 'Time'], axis=1).count(axis=1) %timeit df[list('abcde')].count(axis=1) %timeit df[['a', 'b', 'c', 'd', 'e']].count(axis=1) %timeit df[list('abcde')].notnull().sum(axis=1) 1 loops, best of 3: 5.83 s per loop 100 loops, best of 3: 6.15 ms per loop 100 loops, best of 3: 6.49 ms per loop 100 loops, best of 3: 6.04 ms per loop 

Incluya la lista de columns deseadas, o simplemente elimine las dos columns que no desea excluir del conteo, a lo largo de axis=1 (ver documentos) :

 df['Count'] = df.drop(['Close', 'Time'], axis=1).count(axis=1) Close abcde Time Count 0 2051.25 5 4 3 1 1 05:00:00 5 1 2088.25 5 4 3 1 NaN 06:00:00 4 2 2081.50 5 4 3 NaN NaN 07:00:00 3 3 2058.25 5 4 3 NaN NaN 08:00:00 3 4 2042.25 5 4 NaN NaN NaN 09:00:00 2 
 df['Count'] = df[['a', 'b', 'c', 'd', 'e']].apply(lambda x: sum(x.notnull()), axis=1) In [1254]: df Out[1254]: Close abcde Time Count 2015-12-03 2051.25 5 4 3 1 1 05:00:00 5 2015-12-04 2088.25 5 4 3 1 NaN 06:00:00 4 2015-12-07 2081.50 5 4 3 NaN NaN 07:00:00 3 2015-12-08 2058.25 5 4 NaN NaN NaN 08:00:00 2 2015-12-09 2042.25 5 NaN NaN NaN NaN 09:00:00 1