我在R中使用ggplot2绘图,我在组合平滑和连续色标方面遇到了麻烦。更具体地说,我想绘制一堆平滑的线条,并且对于它们中的每一个,我希望它们的颜色在x轴上变化,使得它们例如是在他们的右端点附近最黑暗。如果我用逐点线性曲线(而不是平滑线)来做这件事,我会做类似
的事情d <- data.frame(id = rep(1:100, 10), x = rep(1:10, each = 100),
y = rep(1:10, each = 100) + rnorm(1000),
z = factor(rep(rep(c("a", "b"), each = 10), 500)))
ggplot(d, aes(x = x, y = y, group = id, col = x)) +
geom_line()
完美无缺。但是,如果我尝试使用平滑而不仅仅是连接点,我得不到相同的结果:使用以下代码将所有线条变为黑色:
ggplot(d, aes(x = x, y = y, group = id, col = x)) +
geom_line(stat = "smooth", method = "loess")
关于为什么会发生这种情况以及可以采取哪些措施的任何提示都将非常感谢!我看过this post,这表明必须在绘图之前平滑数据,但我非常希望在ggplot()
调用中完成所有操作。
我已经尝试了两件值得一提的东西。首先,直接使用geom_smooth()
函数没有区别(但确实改变了默认的行颜色):
ggplot(d, aes(x = x, y = y, group = id, col = x)) +
geom_smooth(se = FALSE, method = "loess")
其次,col
似乎确实是目标的正确参数,因为当根据离散变量选择着色时,一切都有效:
ggplot(d, aes(x = x, y = y, group = id, col = z)) +
geom_line(stat = "smooth", method = "loess")
答案 0 :(得分:3)
我在other question中的建议仍然是“正确”的方式。如果您确实不想修改原始数据框,您可以通过broom
包管道,例如:
d %>%
group_by(id) %>%
do(augment(loess(y~x, data = .))) %>%
ggplot(aes(x = x, y = .fitted, group = id, colour = x)) +
geom_line(stat = "identity", aes(colour = x))
在整个过程中,我只使用数据的一个子集(d %>% filter(id %in% 1:10)
)来使其更清晰/更快:
虽然这种方式更“优雅”,但这意味着每次重新绘制图形时都必须运行模型拟合(顺便使用stat_smooth()
时也会发生这种情况)。这可能会使性能(非常)变慢。
另外,你会发现线条很粗糙,不平滑。它们从原始数据中得到平滑,但每个x
值之间的差距太大,无法产生难以区分的曲线。
解决这个问题的方法是明确stat_smooth
正在做什么:从模型中计算x
s和y
s的新数据帧。为此,您向newdata=
提供augment
。这样做的副作用是丢失旧的y
(和z
)值。
d %>%
group_by(id) %>%
do(augment(loess(y~x, data = .),
newdata = data.frame(x = 0.1*(1:100)))) %>%
ggplot(aes(x = x, y = .fitted, group = id, colour = x)) +
geom_line(stat = "identity", aes(colour = x))
最讨厌和不可取的方法是使用stat_smooth
内部计算的变量,这些变量大部分都没有记录,如有变更,恕不另行通知。 Hadley Wickham explicitly discourages this。< / p>
但是,请谨慎对待风!
d %>%
ggplot(aes(x = x, y = y, group = id, colour = x)) +
geom_line(stat = "smooth", method = "loess", aes(colour = ..x..))
最后,当然你可以在colour=
中加入任何类型的代数表达式。试试colour = sin(x^2/2)
。
这说明了为什么没有将其编码为故意用例。它很丑陋,不会添加信息,会分散实际信息。所以也许可以停下来思考为什么你想要这么做。