通过美观映射在ggplot

时间:2018-07-01 20:37:58

标签: r ggplot2 grouping

我将要绘制想要的图,但是还没有弄清楚stat_summary是否是显示所需图的正确方法。

期望的输出是散点图,其中包含每年 个类别中的中线。例如,在下面的图中,我想要类别A中1999、2000和2001的值的中线(即彩色3条线),然后在类别B中相同(所以总共6条中线)。

我看着here,但这似乎没有达到我想要的效果,因为它使用的是切面。

我的情节看起来好像在每个类别的中位数之间之间画一条线。 stat_summary可以只是在每个类别中绘制一条中线吗?还是我需要使用其他方法(例如计算中位数并按类别将每条线添加到绘图中?

enter image description here

可复制的简单示例

library(tidyverse)
library(lubridate)

# Sample data
Date     <- sort(sample(seq(as.Date("1999-01-01"), as.Date("2002-01-01"), by = "day"), 500))
Category <- rep(c("A", "B"), 250)
Value    <- sample(100:500, 500, replace = TRUE)

# Create data frame
mydata   <- data.frame(Date, Category, Value)

# Plot by category and color by year
p <- ggplot(mydata, aes(x = Category, y = Value,
                        color = factor(year(Date))
                        )
            ) + 
  geom_jitter() 
p


# Now add median values of each year for each group
p <- p +
  stat_summary(fun.y = median,
               geom  = "line",
               aes(color = factor(year(Date))),
               group = 1,
               size = 2
               )
p

2 个答案:

答案 0 :(得分:1)

您正在寻找的实际上是一个点,即使它看起来像一条线,因为您不想连接观测值(一条线做什么),您只想显示一个离散值(什么点确实)。

与链接的帖子非常相似的一种方法是制作stat_summary,并使用实质上是大破折号的形状。我调低了抖动点的Alpha和大小,以更好地将它们与中值区分开。对于中位数,我将颜色分配保持不变,但是将组设置为年份和类别之间的相互作用,因此将计算出六个不同的中位数。

请注意,我为随机数生成设置了一个种子,并将结束日期更改为12/31/2001而不是2002年1月1日,因为您说的是您预期3年,但是在一代人中,我得到了1个观测值2002年1月1日。

library(tidyverse)
library(lubridate)

set.seed(987)
Date     <- sort(sample(seq(as.Date("1999-01-01"), as.Date("2001-12-31"), by = "day"), 500))
Category <- rep(c("A", "B"), 250)
Value    <- sample(100:500, 500, replace = TRUE)

# Create data frame
mydata   <- data.frame(Date, Category, Value)

mydata <- mydata %>%
  mutate(year = year(Date) %>% as.factor())

ggplot(mydata, aes(x = Category, y = Value, color = year)) +
  geom_jitter(size = 0.6, alpha = 0.6) +
  stat_summary(fun.y = median, 
               geom = "point",
               aes(group = interaction(Category, year)),
               shape = 95, size = 12, show.legend = F)

reprex package(v0.2.0)于2018-07-01创建。

答案 1 :(得分:1)

这是使用geom_errorbar(而不是stat_summary)的另一种可能性

# Sample data
set.seed(2017);
Date     <- sort(sample(seq(as.Date("1999-01-01"), as.Date("2002-01-01"), by = "day"), 500))
Category <- rep(c("A", "B"), 250)
Value    <- sample(100:500, 500, replace = TRUE)
mydata   <- data.frame(Date, Category, Value)

mydata %>%
    mutate(colour = factor(year(Date))) %>%
    group_by(Category, year(Date)) %>%
    mutate(Median = median(Value)) %>%
    ggplot(aes(Category, Value, colour = colour)) +
    geom_jitter() +
    geom_errorbar(
        aes(ymin = Median, ymax = Median))

enter image description here

说明:我们预先计算每个Category每个year(Date)的中值,并使用geom_errorbar绘制中线。


更新

根据您的评论,如果您想使用summarise来预先计算中位数,则可以将中位数存储在单独的data.frame

df <- mydata %>%
    mutate(Year = as.factor(year(Date))) %>%
    group_by(Category, Year) %>%
    summarise(Median = median(Value))

ggplot(mydata, aes(Category, Value, colour = factor(year(Date)))) +
    geom_jitter() +
    geom_errorbar(
        data = df,
        aes(x = Category, y = Median, colour = Year, ymin = Median, ymax = Median))

它不如第一个解决方案那么干净(因为您需要在geom_errorbar中指定所有美观性),但是结果图是相同的。