如何使数据点拟合主曲线随机变化的曲线?

How to make data points fit a curve with random variation from main curve?

所以基本上,假设你的曲线像 y = log(x)

const y = x => Math.log(x)
console.log(generate(10))
// [0, 0.6931471805599453, 1.0986122886681096, 1.3862943611198906, 1.6094379124341003, 1.791759469228055, 1.9459101490553132, 2.0794415416798357, 2.1972245773362196]

function generate(max) {
  let i = 1
  let ypoints = []
  while (i < max) {
    ypoints.push(y(i++))
  }
  return ypoints
}

现在有了这些点,我们也想以随机量偏离它们,这也遵循某种变化或随机偏离多少的曲线。因此,例如,随着曲线向上和向右变平,y 略微向上或略微向下移动,随着 y 远离 log(x) 标记的可能性降低。所以假设在 1/x.

处逐渐消失

这意味着,它更有可能直接在 log(x) 上或靠近它,而不是远离它。但是我们可以用任何类似的方程交换。

如何让一个简单的 JavaScript 函数为您提供最终坐标集 (x, y),一个包含 x 和 y 坐标的二元组数组?我的尝试没有正确描述我一直试图描述的“根据次级曲线的变分衰减”。

// calling `u` the thing that converts x into a y point.
const u = x => Math.log(x)
// here, `v` is the equation for variation from the main curve, given a y.
const v = y => 1 / y
// `r` is the random variation generator
const r = y => y + (Math.random() * v(y))

const coordinates = generate(10, u, v, r)

console.log(coordinates)

function generate(max, u, v, r) {
  let i = 1
  let coordinates = []
  while (i < max) {
    const x = i++
    const y = r(u(x))
    coordinates.push([ x, y ])
  }
  return coordinates
}

如何取两条曲线并根据第二条曲线生成远离主曲线的随机变化probability/decay-rate?

预期的输出与评论中的第一个数组相差 +- 一些小量(如果我们沿 x 轴有 10 个点)。

// [0, 0.6931471805599453, 1.0986122886681096, 1.3862943611198906, 1.6094379124341003, 1.791759469228055, 1.9459101490553132, 2.0794415416798357, 2.1972245773362196]

所以它可能就像(只是编造这些,它们会更随机地确定):

// [0, 0.69, 1.1, 1.3, 1.43, 1.71, 1.93, 2, 2.21]

请注意它们更可能靠近 log(x) 曲线(因为 1/x 和随机性),而不是更远,它会变为 +-。

提问的主要原因(与这个抽象问题无关)是为了在开发过程中生成虚拟数据,以测试 UI 数据可视化功能,模拟看起来有些逼真的数据。我会为主曲线选择一个更复杂的方程,为变化选择一个类似的衰减方程,并可能生成数百万个点,所以这只是该问题的简化。

我说的是给定下一张图片中的曲线方程,生成随机点,这些点也像下一张图片中的点。

一种方法:

  • 随机抽取一个x.
  • 计算y = f(x).
  • 根据想要的分布获取此点的随机偏移量。
  • Return这点.

const
    f = x => 10 * Math.log(x),
    offset = () => (1 / Math.random() - 1) * (Math.random() < 0.5 || -1),
    canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d');

for (x = 0; x < 100; x++) {
    const
        y = f(x),
        dx = offset(),
        dy = offset();
        
    console.log(x.toFixed(2), y.toFixed(2), dx.toFixed(2), dy.toFixed(2));
    ctx.beginPath();
    ctx.strokeStyle = '#000000';
    ctx.arc(x * 4 , (100 - y) * 4, 0.5, 0, Math.PI * 2, true);
    ctx.stroke();        

    ctx.beginPath();
    ctx.strokeStyle = '#ff0000';
    ctx.arc((x + dx) * 4 , (100 - y + dy) * 4, 2, 0, Math.PI * 2, true);
    ctx.stroke();        
}
<canvas id="canvas" style="border-width: 0; display: block; padding: 0; margin: 0;" width="400" height="400"></canvas>