两点之间的对数分布曲线的正确算法是什么?

dbu*_*rke 5 algorithm logarithm tag-cloud

我已经阅读了一些关于生成tagcloud权重的对数分布的正确方法的教程.他们中的大多数将标签分组为步骤.这对我来说似乎有些愚蠢,所以我根据我读过的内容开发了自己的算法,以便沿着阈值和最大值之间的logarthmic曲线动态分配标签的计数.这是python中的本质:

from math import log
count = [1, 3, 5, 4, 7, 5, 10, 6]
def logdist(count, threshold=0, maxsize=1.75, minsize=.75):
    countdist = []
    # mincount is either the threshold or the minimum if it's over the threshold
    mincount = threshold<min(count) and min(count) or threshold
    maxcount = max(count)
    spread = maxcount - mincount
    # the slope of the line (rise over run) between (mincount, minsize) and ( maxcount, maxsize)
    delta = (maxsize - minsize) / float(spread)
    for c in count:
        logcount = log(c - (mincount - 1)) * (spread + 1) / log(spread + 1)
        size = delta * logcount - (delta - minsize)
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist
Run Code Online (Sandbox Code Playgroud)

基本上,如果没有单个计数的对数计算,它将在点(mincount,minsize)和(maxcount,maxsize)之间生成一条直线.

该算法对两点之间的曲线进行了很好的近似,但存在一个缺点.mincount是一种特殊情况,它的对数产生零.这意味着mincount的大小将小于minsize.我试过编写数字试图解决这个特例,但似乎无法做到正确.目前我只是将mincount视为特殊情况并将" or 1" 添加到logcount行.

是否有更正确的算法在两点之间绘制曲线?

3月3日更新:如果我没弄错的话,我会记录计数,然后将其插入线性方程式.换句话说,在y = lnx,x = 1时,y = 0.这就是mincount所发生的事情.但是mincount不能为零,标签没有使用过0次.

尝试代码并插入您自己的数字进行测试.将mincount作为特殊情况处理对我来说很好,我觉得它比这个问题的实际解决方案更容易.我觉得必须有一个解决方案,有人可能想出一个解决方案.

更新4月6日:一个简单的谷歌搜索变成了许多我读过的教程,但是很可能是阶梯式标签云的最完整的例子.

更新4月28日:响应antti.huima的解决方案:当绘制图表时,算法创建的曲线位于两点之间的线下方.我一直试图改变数字,但似乎仍然无法想出一种方法将曲线翻转到线的另一边.我猜测如果函数被改为某种形式的对数而不是指数,它就会完全符合我的需要.那是对的吗?如果是这样,有人可以解释如何实现这一目标吗?

dbu*_*rke 2

感谢antti.huima的帮助,我重新思考了我想要做什么。

采用他解决问题的方法,我想要一个方程,其中 mincount 的对数等于两点之间的线性方程。

weight(MIN) = ln(MIN-(MIN-1)) + min_weight
min_weight = ln(1) + min_weight
Run Code Online (Sandbox Code Playgroud)

虽然这给了我一个很好的起点,但我需要让它通过点 (MAX, max_weight)。它需要一个常数:

weight(x) = ln(x-(MIN-1))/K + min_weight
Run Code Online (Sandbox Code Playgroud)

求解 K 我们得到:

K = ln(MAX-(MIN-1))/(max_weight - min_weight)
Run Code Online (Sandbox Code Playgroud)

所以,把这一切放回到一些 python 代码中:

from math import log
count = [1, 3, 5, 4, 7, 5, 10, 6]
def logdist(count, threshold=0, maxsize=1.75, minsize=.75):
    countdist = []
    # mincount is either the threshold or the minimum if it's over the threshold
    mincount = threshold<min(count) and min(count) or threshold
    maxcount = max(count)
    constant = log(maxcount - (mincount - 1)) / (maxsize - minsize)
    for c in count:
        size = log(c - (mincount - 1)) / constant + minsize
        countdist.append({'count': c, 'size': round(size, 3)})
    return countdist
Run Code Online (Sandbox Code Playgroud)