我有一个Django应用程序,我需要在其中实现一个简单的趋势/排名算法。作为一个人,我很迷茫:
我有两个型号,Book和Reader。每天晚上,我的数据库中都会添加新的书籍。每本书的读者数量也是每天晚上更新的,即一本书将有多个读者统计记录(每天一条记录)。
在给定的一段时间内(过去的一周、过去的一个月或过去的一年),我想列出最受欢迎的书籍,我应该使用什么算法?
受欢迎程度不需要以任何方式实时,因为每本书的读者计数只是每天更新。
我发现一篇文章在另一篇文章中引用了SO post that showed how they calculated trending Wikipedia articles,但这篇文章只显示了当前趋势是如何计算出来的。
正如有人指出的那样,它是一个非常简单的基线趋势算法,只计算两个数据点之间的斜率,所以我猜它显示了昨天和今天之间的趋势。
我不是在寻找一个超级复杂的趋势算法,如黑客新闻,Reddit等。
我只有两个数据轴,读者计数和日期。
任何关于我应该实现什么和如何实现的想法。对于从未使用过任何与统计/算法相关的东西的人来说,这似乎是一项非常令人生畏的任务。
提前感谢大家。
发布于 2012-02-15 05:01:42
也许我能想到的最简单的趋势“算法”是n日移动平均线。我不确定你的数据是如何构造的,但是假设你有这样的东西:
books = {'Twilight': [500, 555, 580, 577, 523, 533, 556, 593],
'Harry Potter': [650, 647, 653, 642, 633, 621, 625, 613],
'Structure and Interpretation of Computer Programs': [1, 4, 15, 12, 7, 3, 8, 19]
}一个简单的移动平均值只取最后一个n值,并对它们求平均:
def moving_av(l, n):
"""Take a list, l, and return the average of its last n elements.
"""
observations = len(l[-n:])
return sum(l[-n:]) / float(observations)切片表示法只抓取列表的尾部,从第n个变量到最后一个变量。移动平均线是一种相当标准的方法,可以平滑单个尖峰或低点可能引入的任何噪声。该函数的用法如下:
book_scores = {}
for book, reader_list in books.iteritems():
book_scores[book] = moving_av(reader_list, 5)你会想玩弄一下你平均的天数。如果你想强调最近的趋势,你也可以考虑使用像weighted moving average这样的东西。
如果你想关注一些看起来不是绝对读者群的东西,而是关注读者群的增长,只需找到30日移动平均线和5日移动平均线的百分比变化:
d5_moving_av = moving_av(reader_list, 5)
d30_moving_av = moving_av(reader_list, 30)
book_score = (d5_moving_av - d30_moving_av) / d30_moving_av有了这些简单的工具,你就有了相当大的灵活性,你可以在多大程度上强调过去的趋势,以及你想要平滑(或不平滑)峰值的程度。
发布于 2012-02-15 04:59:43
受欢迎程度很简单;您只需对读者进行计数并按其排序即可:
Book.objects.annotate(reader_count=Count('readers')).order_by('-reader_count')趋势分析更难,因为这是一个更受欢迎的增量,即哪些书最近获得了最多的读者。如果你想要这样的东西,你需要一些在幕后运行的东西来按日期记录读者数量。
发布于 2012-02-15 05:00:34
您可以以stackoverflow reputation ranking为例。
用户可以更改视图:按月、按年、....
以你为例:按月、按年阅读最多的书。
要做到这一点,你应该每天节省每本书的读者数量。
reader( date, book, total )然后它就像下面这样简单:
Book.objects.filter(
boor__reader__date__gte = some_date
).annotate(
num_readers=Sum('book__reader__total')
).order_by('-num_readers')https://stackoverflow.com/questions/9283856
复制相似问题