把大区间的数据转成小区间的数据
一、需求场景
先上一张效果图:
产品需求是这样子的:把各部剧目的播放指数最高的八个省份,在左侧的地图中用实心圆进行标注,指数越高,圆的半径越大。在右侧用条形图把这top 8的省份展示出来,指数越高,条的长度越长。
限于页面展示空间,地图标注时,圆的半径取值范围为[4,10]
,条的width取值范围在[10%,100%]
(条形图由css实现,js通过设置width的百分比来适应数据),即指数最高的省份在标记时用半径为10的圆和width为100%的条,第八高的省份用半径为4的圆和width为10%的条。
问题现在归结为:把最高的八个省份的指数,转换输出为[4,10]和[10%, 100%]区间之内的数,同时要保证单调递增,越大的指数,转换后的半径和width越大。
现在来看看输入,最高的八个省份的指数数据分布是什么样子呢? 以生活启示录当前的top 8指数数据为例:
[{"name":"上海","value":4186447},{"name":"江苏","value":2505809},{"name":"黑龙江","value":2410871},
{"name":"北京","value":2090109},{"name":"湖南","value":1889304},{"name":"安徽","value":1818746},
{"name":"陕西","value":1749618},{"name":"天津","value":1698673}]
区间为[1698673, 4186447]
,与输出区间[4,10]
和[0.1,1]
无比例关系。线上的输入区间范围可能更大,因为取的是用户选择的三部剧进行对比,最大值是最热门的剧的指数最高的省份的指数,最小值是最冷门的剧的第八高省份的指数,这种情况下输入的最大值和最小值可能差别好几个数量级。
现在问题就成了:给定任意大小的区间[minInput, maxInput]
, 提供单调递增转换方法,将输入区间内的数输出为[minOutput, maxOutput]
的数。
二、解决方案
不啰嗦废话了,直接写一下解决方法:线性函数转换
就是用函数y = a * x + b
对输入数据进行处理,问题就是求参数a和b。求法为解下面的方程:
minOutput = a * minInput + b
maxOutput = a * maxInput + b
求解出来的结果是:
a = (maxOutput - minOutput) / (maxInput - minInput)
b = minOutput - a * minInput
线性转换是最简单的方式了,这类问题,称为数据归一化,or 数据处理之标准化/归一化。
三、花絮
我是怎么知道这个问题的解决方法的呢?
嘿嘿,是我求助我们公司用户行为分析团队的同事,他们告诉我的!他们负责提供这次视频指数页面的数据。
其实他们还告诉我一个听起来更高大上的方法:sigmoid函数f(x) = 1/[1+e^(-x)]
。我粗略看一下,这个函数在x趋于正无穷时值为1,在x趋于负无穷时值为0,还要再调整下sigmoid函数才能满足我的需求:x趋于maxInput时,值为10,x趋于minInput时值为4。我觉得这个函数看上去太复杂,就没采用sigmoid函数(其实是我不会啊!)。
blog comments powered by Disqus