2011-08-23 34 views
8

Daré un contexto para que tenga sentido. Estoy capturando las valoraciones de los clientes de los productos en una tabla (clasificación) y quiero poder devolver una media móvil acumulativa de las calificaciones según el tiempo.Cómo calcular la media móvil acumulativa en Python/SQLAlchemy/Flask

Un ejemplo básico sigue teniendo una calificación por día:

02 FEB - Rating: 5 - Cum Avg: 5 
03 FEB - Rating: 4 - Cum Avg: (5+4)/2 = 4.5 
04 FEB - Rating: 1 - Cum Avg: (5+4+1)/3 = 3.3 
05 FEB - Rating: 5 - Cum Avg: (5+4+1+5)/4 = 3.75 
Etc... 

Estoy tratando de pensar en un enfoque que no se escala horrible.

Mi idea actual es tener una función que se dispara cuando se inserta una fila en la tabla de clasificación que se resuelve el Cum Promedio basado en la fila anterior de ese producto

Así los campos sería algo así como:

TABLE: Rating 
| RatingId | DateTime | ProdId | RatingVal | RatingCnt | CumAvg | 

Pero esto parece una manera bastante peligrosa de almacenar los datos.

¿Cuál sería la (o alguna) forma de lograr esto? Si tuviera que usar el 'disparador' de géneros, ¿cómo haces eso en SQLAlchemy?

¡Todos y cada uno de los consejos apreciados!

+1

Definitivamente es posible hacer esto en SQL - ver: http://stackoverflow.com/questions/4107479/subqueries-aggregates-and-aggravation/4107784#4107784 ... No estoy seguro de cómo obtener SQLAlchemy para generar una consulta como esa (y su base de datos puede no ser compatible con la sintaxis necesaria). –

+0

@Sean Vieria: Gracias por el enlace - Sé que es posible en SQL puro, pero nuevamente esto significa que a medida que crece el número de evaluaciones, el rendimiento empeora a medida que los cálculos se realizan en cada fila. Podría intentar implementar mi idea original de almacenarlo a medida que se ingresa cada fila, ya que sé que se escalará. Simplemente no estaba seguro de si había algo básico que estaba pasando por alto. ¡Gracias por la ayuda! – mwan

Respuesta

5

No sé sobre SQLAlchemy, pero podría utilizar un enfoque de esta manera:

  • Almacene el promedio acumulativo y el recuento de calificación por separado de las calificaciones individuales.
  • Cada vez que reciba una nueva calificación, actualizar la media y la Cuenta de clasificación acumulada:
    • NEW_COUNT = old_count + 1
    • new_average = ((old_average * old_count) + new_rating)/NEW_COUNT
  • Opcionalmente, almacene una fila para cada nueva calificación.

La actualización del promedio y el recuento de calificación se pueden realizar con una sola instrucción de SQL.

+0

Gracias, implementé la mayor parte de ayer y este es el enfoque que terminé tomando de todos modos, tengo que terminar de implementarlo y luego voy a publicar el código que utilicé.Se escala de manera responsable y predecible, que es lo que yo buscaba. – mwan

+0

Y si el usuario puede editar la calificación? Este enfoque funcionaría? – user2990084

+1

Es mucho más fácil almacenar la * suma * y el recuento, en lugar del * promedio * y el recuento. –

-5

creo que debe almacenar el MA en una lista 2 elemento, que sería mucho más simple:

#first rating 5 is rating number 0 
a = [5,0] 

#next: 
for i in rating: 
a = [(a[0]*a[1]+lastRating)/(a[1]+1),a[1]+1] 

adiós

+0

¿Sugiere que almacene la lista del lado de Python (es decir, que tenga que volver a calcular la lista completa para cada consulta que se ejecuta)? No estoy seguro de seguir. ¿No sería tan grave a medida que crezca el número de calificaciones? – mwan

Cuestiones relacionadas