如何在 R 中绘制具有标准化 x 轴的多条线?

How to plot multiple lines with a normalised x axis in R?

     distance1  grey1    distance2  grey2
1    0.0000000 -300.364  0.0000000 -135.219
2    0.2174741 -296.963  0.2114969 -132.601
3    0.4349482 -292.887  0.4229937 -131.959
4    0.6520882 -290.310  0.6341657 -133.514
5    0.8695623 -285.777  0.8456625 -127.111
6    1.0870364 -279.921  1.0571594 -116.404
7    1.3045105 -274.418  1.2686562 -116.850
8    1.5216505 -272.005  1.4798282 -115.464
9    1.7391246 -273.666  1.6913251 -102.823
10   1.9565987 -270.381  1.9028219 -101.497
11   2.1740728 -270.273  2.1143188  -98.245
12   2.3912128 -270.705  2.3254907  -98.474

我的 x 轴是我标准化为 0-100 的距离。我的 Y 轴是整个距离的强度值。我有 2 个样本,其中每个 Y 值都匹配一个特定的 X 值(注意样本 2 的行数比样本 1 多)。 我粘贴了前几行数据作为示例。如何在同一个图中绘制两个样本的图?之后如何创建 2 个样本的平均图?

不太清楚您要做什么,所以我将提供几个演示。首先,我假设您在这里有两个不同的数据集,第一个在第 1-2 列,第二个在第 3-4 列。这可以在ggplot2按字面意思完成:

library(ggplot2)
ggplot(dat) +
  geom_line(aes(distance, grey1), color="red") +
  geom_line(aes(distance1, grey2), color="blue")

但这种方法有点brute-forcing,并且会使诸如传说、color-control等之类的东西变得相当痛苦。我建议这个过程将受益于将数据重塑为 long-format,其中只有 x 和 y 变量加上一个来指示该行来自哪个组。例如,

library(data.table)
newdat <- data.table::melt(as.data.table(dat),
    measure = patterns("^distance","^grey"),
    value.name = c("distance", "grey"))
newdat
#     variable  distance     grey
#       <fctr>     <num>    <num>
#  1:        1 0.0000000 -300.364
#  2:        1 0.2174741 -296.963
#  3:        1 0.4349482 -292.887
#  4:        1 0.6520882 -290.310
#  5:        1 0.8695623 -285.777
#  6:        1 1.0870364 -279.921
#  7:        1 1.3045105 -274.418
#  8:        1 1.5216505 -272.005
#  9:        1 1.7391246 -273.666
# 10:        1 1.9565987 -270.381
# ---                            
# 15:        2 0.4229937 -131.959
# 16:        2 0.6341657 -133.514
# 17:        2 0.8456625 -127.111
# 18:        2 1.0571594 -116.404
# 19:        2 1.2686562 -116.850
# 20:        2 1.4798282 -115.464
# 21:        2 1.6913251 -102.823
# 22:        2 1.9028219 -101.497
# 23:        2 2.1143188  -98.245
# 24:        2 2.3254907  -98.474

新的 variable 列表示数据来自哪个 column-group。

这里,ggplot 中的绘图变得更简单一些:

ggplot(newdat, aes(distance, grey)) +
  geom_line(aes(color = variable, group = variable))

请注意,我们现在有一个图例,它正在处理颜色本身。这些可以被覆盖,但这是一个不同的主题(并在此处的许多问题中解决)。


至于 “2 个样本的平均图”,这将在数据中包含更多上下文,目前 well-enough 未获悉。我最担心的是每组数据的 distancegrey 都没有完全对齐。也就是说,如果 distance 在两者中的值都正好是 1.000,那么我认为我们可以安全地对这两个观察值的 grey 值进行平均。但是,一般情况并非如此(此样本数据集中的任何地方也不是)。

如果您真的想找到一种形式的平均值,我建议您将两条线插入到 distance 的已知域中并显示平均值。我会演示我的意思。

首先,我将添加点以便我们可以看到 x-wise 错位:

ggplot(newdat, aes(distance, grey, color = variable)) +
  geom_line() +
  geom_point()

现在,让我们汇总“平均值”(来自插值 distance 并将它们添加到原始 long-form 数据中。

newdist <- seq(0, min(max(dat$distance), max(dat$distance1)), by = 0.1)
newdat2 <- newdat[, setNames(approx(distance, grey, xout = newdist), c("distance", "grey")), by = variable
  ][, .(variable = "Avg", grey = mean(grey)), by = distance]
newdat2 <- rbindlist(list(newdat, newdat2), use.names = TRUE)

现在,我们可以使用 same plot 命令并得到第三行:

ggplot(newdat2, aes(distance, grey, color = variable)) +
  geom_line() +
  geom_point()

此方法正在对数据进行一些推论,我们在问题中没有太多的推论。我认为这是一个安全的步骤,但在盲目地对您的数据使用此技术之前,请确保它在统计上有意义。


数据(我在重命名列之前开始写这个,所以follow-on代码可能需要调整)。

dat <- structure(list(distance = c(0, 0.2174741, 0.4349482, 0.6520882, 0.8695623, 1.0870364, 1.3045105, 1.5216505, 1.7391246, 1.9565987, 2.1740728, 2.3912128), grey1 = c(-300.364, -296.963, -292.887, -290.31, -285.777, -279.921, -274.418, -272.005, -273.666, -270.381, -270.273, -270.705), distance1 = c(0, 0.2114969, 0.4229937, 0.6341657, 0.8456625, 1.0571594, 1.2686562, 1.4798282, 1.6913251, 1.9028219, 2.1143188, 2.3254907), grey2 = c(-135.219, -132.601, -131.959, -133.514, -127.111, -116.404, -116.85,  -115.464, -102.823, -101.497, -98.245, -98.474)), class = "data.frame", row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"))