我一直在使用geom_violin
的修改版本制作如下图:
但是,我意识到可以直接使用stat_ydensity
来实现此情节。不幸的是,我无法正常工作:
ggplot(res.plot, aes(x = time, y = x,group = run)) + theme_bw() +
geom_line(alpha = 0.1) +
stat_ydensity(aes(group = time), data = res.select,
geom = "density", color = "red")
我尝试使用geom = "path"
和geom = "line"
,并尝试使用例如position = "identity"
和position = position_dodge(width = 2)
,但无法生成顶部图。
任何人都可以解释我在做什么吗?下面的res.plot
和res.select
数据框的代表:
library(tidyr)
library(ggplot2)
library(dplyr)
# markov chain parameters
mu = 8 # cm/hr
sigma = 4 # cm/sqrt(hr)
x0 = 3 # initial condition
tmax = 200 # end time
deltat = 10 # time increment (hrs)
reps = 300 # number of realizations
random_walk = function()
c(0, cumsum(mu*deltat + sigma*rnorm(n, sd = deltat))) + x0
# simulate random walks
n = tmax/deltat
res = cbind.data.frame(seq(0,tmax, by = deltat), replicate(reps, random_walk()))
names(res) = c("time", paste("run", seq(1, ncol(res) - 1)))
# format the data for plotting
res.plot = gather(res, run, x, -time)
# extract specific times to compute marginal densities
res.select = filter(res.plot, time %in% c(50, 150))
答案 0 :(得分:1)
这不是“答案”,因为它不能解决问题,但可以帮助OP理解为什么它不起作用:
ggplot(res.plot, aes(x = time, y = x, group = run)) + theme_bw() +
geom_line(alpha = 0.1) +
stat_ydensity(aes(group = time), data = res.select,
geom = "density", color = "red") -> gg
gb <- ggplot_build(gg)
str(gb$data[[2]])
## 'data.frame': 1024 obs. of 20 variables:
## $ x : num 50 50 50 50 50 50 50 50 50 50 ...
## $ density : num 0.000139 0.000144 0.000149 0.000154 0.000159 ...
## $ scaled : num 0.0308 0.0319 0.033 0.0342 0.0354 ...
## $ ndensity : num 0.0308 0.0319 0.033 0.0342 0.0354 ...
## $ count : num 0.0417 0.0432 0.0447 0.0462 0.0478 ...
## $ n : int 300 300 300 300 300 300 300 300 300 300 ...
## $ y : num 178 179 180 181 182 ...
## $ group : int 1 1 1 1 1 1 1 1 1 1 ...
## $ PANEL : Factor w/ 1 level "1": 1 1 1 1 1 1 1 1 1 1 ...
## $ violinwidth: num 0.0308 0.0319 0.033 0.0342 0.0354 ...
## $ ymin : num 0 0 0 0 0 0 0 0 0 0 ...
## $ ymax : num 178 179 180 181 182 ...
## $ xmin : num 50 50 50 50 50 50 50 50 50 50 ...
## $ xmax : num 50 50 50 50 50 50 50 50 50 50 ...
## $ colour : chr "red" "red" "red" "red" ...
## $ fill : chr "#617a89" "#617a89" "#617a89" "#617a89" ...
## $ weight : num 1 1 1 1 1 1 1 1 1 1 ...
## $ alpha : logi NA NA NA NA NA NA ...
## $ size : num 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 ...
## $ linetype : num 1 1 1 1 1 1 1 1 1 1 ...
查看density
的值(及其同级物)。这是计算出的密度,请记住,密度图曲线下的面积== 1。stat_ydensity()
中没有选项,就像geom_density()
可以进行数学计算并为您获取计数一样代替。
您可以尝试采用gb$data[[2]]
,重新计算路径的点,并在以后手动添加。但是,保持本地geom并在ggplot2版本上放一块手表以在必要时进行更新也没有什么错。我一直都这样做。
答案 1 :(得分:1)
这似乎是不可能的,因为您需要将计算出的变量映射到x
,但是stat_ydensity()
需要x
才能计算值。这是一个死锁。
library(tidyr)
library(ggplot2)
library(dplyr, warn.conflicts = FALSE)
# markov chain parameters
mu = 8 # cm/hr
sigma = 4 # cm/sqrt(hr)
x0 = 3 # initial condition
tmax = 200 # end time
deltat = 10 # time increment (hrs)
reps = 300 # number of realizations
random_walk = function()
c(0, cumsum(mu*deltat + sigma*rnorm(n, sd = deltat))) + x0
# simulate random walks
n = tmax/deltat
res = cbind.data.frame(seq(0,tmax, by = deltat), replicate(reps, random_walk()))
names(res) = c("time", paste("run", seq(1, ncol(res) - 1)))
# format the data for plotting
res.plot = gather(res, run, x, -time)
# extract specific times to compute marginal densities
res.select = filter(res.plot, time %in% c(50, 150))
ggplot(res.plot, aes(x = time, y = x,group = run)) + theme_bw() +
geom_line(alpha = 0.1) +
stat_ydensity(aes(group = time, x = stat(violinwidth)), data = res.select,
geom = "point", color = "red")
#> Error: stat_ydensity requires the following missing aesthetics: x
当然,可以映射x
以外的其他变量。
ggplot(res.plot, aes(x = time, y = x,group = run)) + theme_bw() +
geom_line(alpha = 0.1) +
stat_ydensity(aes(group = time, size = stat(violinwidth)), data = res.select,
geom = "point", color = "red")
#> Warning: Width not defined. Set with `position_dodge(width = ?)`
在Geom内部函数中使用没有显式映射的变量也是可以的。我猜geom_ydensity()
使用了这种方式。也许您需要为此创建一个新的Geom?