16

我有一个 Django 应用程序,我需要在其中实现一个简单的趋势/排名算法。我很迷茫:

我有两个模型,BookReader。每天晚上,新书都会添加到我的数据库中。每本书的读者数量也在每晚更新,即一本书将有多个读者统计记录(每天一条记录)。

在给定的时间段内(过去一周、过去一个月或过去一年),我想列出最受欢迎的书籍,我应该使用什么算法?

流行度不需要以任何方式实时,因为每本书的读者人数仅每天更新。

我发现一篇文章在另一篇 SO帖子中被引用,该文章显示了他们如何计算热门 Wikipedia 文章,但该帖子仅显示了当前趋势是如何计算的。

正如有人在 SO 上指出的那样,这是一个非常简单的基线趋势算法,只计算两个数据点之间的斜率,所以我猜它显示了昨天和今天之间的趋势。

我不是在寻找像 Hacker News、Reddit 等上使用的超级复杂的趋势算法。

我只有两个数据轴,读者人数和日期。

关于我应该实施什么以及如何实施的任何想法。对于从未使用过任何与统计/算法相关的东西的人来说,这似乎是一项非常艰巨的任务。

提前谢谢大家。

4

4 回答 4

8

可能我能想到的最简单的趋势“算法”是 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)

你会想玩弄你平均的天数。如果你想强调最近的趋势,你也可以考虑使用加权移动平均线之类的东西。

如果您想专注于不太关注绝对读者人数而关注读者人数增加的事情,只需找到 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-14T21:01:41.953 回答
0

流行很容易;您只需对读者进行计数并按以下顺序排序:

Book.objects.annotate(reader_count=Count('readers')).order_by('-reader_count')

趋势更难,因为这更像是一个受欢迎的增量,即最近哪些书获得了最多的读者。如果你想要这样的东西,你需要在幕后运行一些东西来按日期记录读者数量。

于 2012-02-14T20:59:42.947 回答
0

您可以以stackoverflow 信誉排名为例。

用户可以更改视图:按月、按年、....

在你的情况下:按月,按年阅读最多的书。

为了实现这一点,您应该每天节省每本书的读者数量。

reader( date, book, total )

然后它很简单:

   Book.objects.filter(  
                   boor__reader__date__gte = some_date
                      ).annotate(
                            num_readers=Sum('book__reader__total')
                                ).order_by('-num_readers')
于 2012-02-14T21:00:34.183 回答
0

我会像这样系统地这样做:

  1. 列出用户最感兴趣的最常见问题或数据点,例如: 1.1 本周最受欢迎的 100 本书 1.2 本月最受欢迎的 100 本书

  2. 在您的每日读者/书籍信息之后。已更新,我会运行一项工作(可能是每晚)来更新此信息的表格。表可能会有 Book 和 ReaderDelta 字段,其中 ReaderDelta 是 readerCount 在一周、一个月或一年内的变化。

  3. 您还可以简单地存储每日 ReaderDelta,并在查找一个月的数据时,只需按日期动态汇总过去 30 天。

于 2012-02-14T21:22:51.520 回答