R ggplot2中的平滑和连续颜色渐变

R ggplot2中的平滑和连续颜色渐变,r,plot,ggplot2,colors,R,Plot,Ggplot2,Colors,我在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),

我在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()
调用中完成所有操作


我已经尝试了两件值得一提的事情。首先,直接使用
geom_smooth()
函数不会产生任何影响(但会更改默认线颜色):

其次,
col
似乎是正确的目标参数,因为当根据离散变量选择颜色时,一切正常:

ggplot(d, aes(x = x, y = y, group = id, col = z)) +
       geom_line(stat = "smooth", method = "loess")  
我的建议仍然是做这件事的“正确”方式。如果您确实不想修改原始数据帧,可以通过管道通过
扫帚
包,如下所示:

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%在%1:10中)
),以使其更清晰/更快:

虽然这种方法更“优雅”,但它意味着每次重新绘制图形时都必须运行模型拟合(顺便说一下,使用
stat\u smooth()
时也会发生这种情况)。这会使性能(非常)缓慢

此外,你会注意到线条是扭曲的,不平滑的。它们从原始数据平滑,但每个
x
值之间的间隙太大,无法生成难以区分的曲线

解决这个问题的方法是明确说明
stat\u smooth
正在做什么:从模型中计算
x
s和
y
s的新数据帧。为此,您需要将
newdata=
提供给
augment
。这样做的副作用是您丢失了旧的
y
(和
z
)值

最老练和不可取的方法是使用
stat\u smooth
的内部计算变量,这些变量大多未记录在案,如有更改,恕不另行通知。Hadley Wickham

但让我们把谨慎抛在脑后吧

d %>% 
  ggplot(aes(x = x, y = y, group = id, colour = x)) +
  geom_line(stat = "smooth", method = "loess", aes(colour = ..x..))

最后,您当然可以为
color=
添加任何类型的代数表达式。试试
color=sin(x^2/2)

这说明了为什么没有将其编码为有意的用例。它很难看,不添加信息,而且会分散对实际信息的注意力。所以,也许停下来好好想想你为什么要这么做。

我的建议仍然是“正确”的方式。如果您确实不想修改原始数据帧,可以通过管道通过
扫帚
包,如下所示:

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%在%1:10中)
),以使其更清晰/更快:

虽然这种方法更“优雅”,但它意味着每次重新绘制图形时都必须运行模型拟合(顺便说一下,使用
stat\u smooth()
时也会发生这种情况)。这会使性能(非常)缓慢

此外,你会注意到线条是扭曲的,不平滑的。它们从原始数据平滑,但每个
x
值之间的间隙太大,无法生成难以区分的曲线

解决这个问题的方法是明确说明
stat\u smooth
正在做什么:从模型中计算
x
s和
y
s的新数据帧。为此,您需要将
newdata=
提供给
augment
。这样做的副作用是您丢失了旧的
y
(和
z
)值

最老练和不可取的方法是使用
stat\u smooth
的内部计算变量,这些变量大多未记录在案,如有更改,恕不另行通知。Hadley Wickham

但让我们把谨慎抛在脑后吧

d %>% 
  ggplot(aes(x = x, y = y, group = id, colour = x)) +
  geom_line(stat = "smooth", method = "loess", aes(colour = ..x..))

最后,您当然可以为
color=
添加任何类型的代数表达式。试试
color=sin(x^2/2)


这说明了为什么没有将其编码为有意的用例。它很难看,不添加信息,而且会分散对实际信息的注意力。所以,也许停下来好好想想为什么你要这么做。

当你使用平滑器时,它是在计算一个新的变量,而你无法真正将值映射到它。尝试预先计算黄土外部平滑器,并将
x
映射为颜色,就像对
geom_line()
所做的那样。使用平滑器时,它正在计算一个新变量,而您无法将值映射到该变量。尝试预先计算黄土的外部平滑度,并将
x
映射为颜色,就像您为
geom\u line()
所做的那样。非常感谢您提供了非常全面的答案!最后,我希望使用该方法绘制具有不同端点的平滑线,并根据线的距离对线进行着色。基本上,我想让它更容易地看到在一条线停止之前是否发生了什么特别的事情-因此除了这个最小的例子之外,它还有一些意义。但是,如果你不介意的话,我有一个后续的问题:在我看来,你觉得在geom_线()中进行所有操作在某种程度上是“错误的”。我理解ggplot实现不允许以非黑客方式进行此操作,当然,这是不进行此操作的一个有效原因,但是否还有其他我忽略的问题(显然,除了计算时间问题之外)?因为我在这里的下一步将是自己编写一个支持添加颜色的geom_line2()函数
d %>% 
  ggplot(aes(x = x, y = y, group = id, colour = x)) +
  geom_line(stat = "smooth", method = "loess", aes(colour = ..x..))