2012-06-18 9 views
7

tengo algoritmo de cálculo de la velocidad media en Python puro:Numpy significar con la condición

speed = [...] 
    avg_speed = 0.0 
    speed_count = 0 
    for i in speed: 
     if i > 0: # I dont need zeros 
      avg_speed += i 
      speed_count += 1 

    if speed_count == 0: 
     return 0.0 

    return avg_speed/speed_count 

¿Hay alguna manera de volver a escribir esto funciona con Numpy?

Respuesta

9
import numpy as np 

def avg_positive_speed(speed): 
    s = np.array(speed) 
    positives = s > 0 
    if positives.any(): 
     return s[positives].mean() 
    else: 
     return 0. 


speed = [1., 2., 0., 3.] 
print avg_positive_speed(speed) 
# prints 2.0 

print avg_positive_speed([0., 0.]) 
# prints 0.0 
3

Sé que usted quiere una solución numpy, por lo que este no cumple con ese criterio (@ post anterior de eumiro sin duda lo hace), pero sólo como una alternativa, aquí es una versión optimizada del pitón que, sorprendentemente, (a mí por lo menos) resultó ser bastante rápido!

speeds = [i for i in speed if i > 0] 
return sum(speeds)/(1.0 * len(speeds)) if sum(speeds) > 0 else 0.0 

podría ser interesante comparar esto con la numpy (o el original) aplicación en términos de velocidad.

In [14]: timeit original(speed)    # original code 
1000 loops, best of 3: 1.13 ms per loop 

In [15]: timeit python_opt(speed)   # above Python 2 liner 
1000 loops, best of 3: 582 us per loop 

In [16]: timeit avg_positive_speed(speed) # numpy code 
1000 loops, best of 3: 1.2 ms per loop 

donde

speed = range(10000) 

yo habría pensado que numpy tendría la ventaja aquí .. Alguien sabe por qué senderos?

Actualización:

con speed = range(100000):

In [19]: timeit original(speed) 
100 loops, best of 3: 12.2 ms per loop 

In [20]: timeit python_opt(speed) 
100 loops, best of 3: 11 ms per loop 

In [21]: timeit avg_positive_speed(speed) 
100 loops, best of 3: 12.5 ms per loop 

Todavía no está convencido de que numpy es una buena herramienta para este problema particular, a menos que haya un número enorme de velocidades :)

¿Cómo maneja numpy la memoria? la comprensión de la lista en algún momento tropezará con algunas limitaciones.

+0

Pruebe números más grandes. Con 1000, la conversión de una lista a una matriz está dominando los tiempos. –

+0

@JoeKington simplemente haciendo esto ahora ... :) – Levon

+2

Tenga en cuenta que la conversión de una lista grande a una matriz numpy es un proceso relativamente lento. Si los datos ya son una matriz numpy (que usa _far_ menos memoria que una lista), entonces las versiones numpy serán mucho más rápidas. De lo contrario, no verá una gran diferencia para una sola operación, ya que la mayor parte del tiempo se consumirá convirtiendo la lista en una matriz. –

16

La función numpy.average puede recibir un argumento weights, donde se puede poner una matriz booleana generado a partir de una cierta condición aplicada a la matriz en sí - en este caso, al ser un elemento mayor que 0:

average_speed = numpy.average(speeds, weights=(speeds > 0)) 

Esperanza esta ayuda

+4

+1, ¡esta pista de 'pesos 'es maravillosa! – eumiro

+0

Esta solución es genial, gracias. –

9

me sorprende que nadie ha sugerido la solución más corta:

speeds_np = np.array(speeds) 

speeds_np[speeds_np>0].mean() 

Explicación:

speedsNp > 0 crea una matriz booleana del mismo tamaño que satisface la igualdad (in). Si se introduce en speedsNp, solo arroja los valores correspondientes de speedNp donde el valor de la matriz booleana es True. Todo lo que necesita hacer entonces, es simplemente tomar el mean() del resultado.

+1

Esta es definitivamente la mejor respuesta aquí. Gracias @TimY – mjp