2

I have a ranking system where users can upvote/downvote(+1/-1) objects, and each object has a cumulative rating_sum, which can be negative, zero or positive. I also record total number of times the objects has been rated in rating_count. I can thus get the number of up votes and down votes with a bit of algebra.

I want to implement a scoring algorithm that takes into account the objects rating, but also means older objects get penalised and have a lower score.

So far I found the following:

score=rating_sum/(age^gravity)

where gravity is some constant (I've been using gravity=2).

This works OK, except for ratings with negative values, in which case the older the object, the greater (less negative) its score. This means that given two objects with the same negative rating, say -2, the older one scores above the younger, and floats higher.

Is there a scoring algorithm out there I could use that would work for negative ratings too?

(For technical reasons (I'm trying to optimize by using the django ORM), I would like an algo that is fairly simple and I can put into an SQL query statement, so just POW, LOG preferably)

fpghost
  • 2,834
  • 4
  • 32
  • 61
  • Why not `score = rating_sum - age^gravity`? Think of `rating_sum` as the "popularity" and `-1 * age^gravity` as the "freshness". Then `score = popularity + freshness`. – Timothy Shields Aug 22 '14 at 15:11

2 Answers2

0

You could use an exponential decay model.

http://en.wikipedia.org/wiki/Exponential_decay

Have your lambda be based on your current rating. Something like (lambda = - rating/constant)

With that if lambda is negative the score will decrease towards 0;

If lambda is positive the score will increase negatively towards negative infinity;

However this means that negative scores are only more negative and positive scores never go negative.

wckd
  • 410
  • 2
  • 9
0

This looks a lot like the "hotness" ranking like Reddit uses. It orders (descending) the LOG10 of the user rating plus the age. This SQL is a rough example:

SELECT *
FROM ratings
ORDER BY 
    LOG10(ABS(rating_sum)) * SIGN(rating_sum)   
    + (UNIX_TIMESTAMP(created_at) / 300000) DESC
LIMIT 50

Beware of when your rating_sum = 0 because taking the log of zero is not cool.

I wrote an article describing it in more detail on one of my sites Reddit Hotness Algorithm in SQL

Chris Broski
  • 2,421
  • 27
  • 23