用ggplot2 :: stat_ydensity绘制横向密度

时间:2018-10-17 19:11:53

标签: r ggplot2

我一直在使用geom_violin的修改版本制作如下图:

Plot with modified version of 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")

failed attempt with stat_ydensity

我尝试使用geom = "path"geom = "line",并尝试使用例如position = "identity"position = position_dodge(width = 2),但无法生成顶部图。

任何人都可以解释我在做什么吗?下面的res.plotres.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))

2 个答案:

答案 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?