如何不使用均值、最值等参数重新缩放非对称分布向量
自定义线性映射实现指定点转换
嘿,我来帮你搞定这个问题!你想要的是一个基于指定点的线性映射,完全不需要依赖分布的最大/最小值参数,咱们一步步拆解:
核心思路:构造线性变换函数
我们需要找到一个线性函数 ( y = a \times x + b ),满足两个映射规则:
- 当原数值 ( x=0 ) 时,新数值 ( y=100 )
- 当原数值 ( x=2 ) 时,新数值 ( y=15 )
推导这个函数非常简单:
- 代入第一个规则:( 100 = a \times 0 + b ) → 直接得出 ( b=100 )
- 代入第二个规则:( 15 = a \times 2 + 100 ) → 解出 ( a = (15-100)/2 = -42.5 )
最终的变换公式就是:( y = -42.5x + 100 )
为什么你的之前尝试没达到预期?
scale(x)*15+100:scale()的作用是标准化数据(减去均值、除以标准差),后续的缩放平移是基于标准化后的结果,完全不是你要的“指定点映射”,所以生成的密度图只是原分布的标准化拉伸,和目标映射无关。scales::rescale(x, from=c(0,2), to=c(100,15)):其实这个方法是可行的!rescale的逻辑是把from区间的端点对应到to的端点——你设置to=c(100,15)刚好是反向映射,所以0→100、2→15的规则是成立的。可能你觉得结果不对,是因为原数据里有超出0-2的部分(比如你生成的x包含2.5附近的数值),这些值会被映射到15以下,这和手动推导的线性变换结果完全一致,都是全局的线性映射。
完整实现代码
这里提供两种可行的变换方式,结果完全一致:
# 生成原非对称分布数据 x <- c(rnorm(100, 0, 1), rnorm(100, 2.5, 0.5)) # 方法1:手动构造线性变换(最直观,完全符合需求) y_manual <- -42.5 * x + 100 # 方法2:使用scales::rescale(简洁实现) library(scales) y_rescale <- rescale(x, from = c(0, 2), to = c(100, 15)) # 画图对比三种分布 par(mfrow = c(1, 3)) # 原分布:双峰非对称,一个峰在0附近,一个在2.5附近 plot(density(x), main = "原非对称分布密度图", xlab = "原数值x") # 手动变换后:原0附近的峰对应100,原2.5附近的峰对应-6.25 plot(density(y_manual), main = "手动线性变换后密度图", xlab = "新数值y") # rescale变换后:和手动变换结果完全一致 plot(density(y_rescale), main = "rescale变换后密度图", xlab = "新数值y")
内容的提问来源于stack exchange,提问作者Dominique Makowski
相关产品推荐
相关产品推荐

