R:facet_grid 使用 ggplot2 绘制的组间差异图

R: facet_grid plot of differences between groups using ggplot2

我正在尝试创建一系列图表来显示测量变量组之间的差异,并且正在寻找一种有效的方法来使用 R 中 ggplot2facet_grid 功能.

这是一个说明性的例子:

# sample input data
df <- data.frame(year=rep(c(2011:2015), 2), 
                 value=c(0:4, 1:5),
                 scenario=rep(c("a","b"), each=5))

# make a sample plot
p <- 
  ggplot(df, aes(x=year, y=value)) +
  geom_point() + geom_line() +
  facet_grid(scenario ~ scenario)

这会生成以下示例图,其中针对每个场景组合分别针对 value 绘制 year

(我假设没有绘制第二行,因为它与第一行相同)。

但是,我正在寻找的是一个图,其中在每个方面,(顶部方案中的值)-(右侧方案中的值)按年份绘制。具体来说:

我无法找到 facet_grid 的任何内置或自动差异命令。我最初的想法是将函数作为 y 参数传递给 ggplot,但考虑到数据框只有一个 value 列,我被难住了。我猜可能有一个使用 dplyrreshape2 的某种组合的解决方案,但我无法理解如何实现它。

这是一个选项,它使用 tidyr 中的一些函数,首先 spread 计算数据以计算对比度,然后 gather 将其组合在一起以允许绘图:

forPlotting <-
  df %>%
  spread(scenario, value) %>%
  mutate(`a - b` = a - b
         , `b - a` = b - a
         , `a - a` = 0
         , `b - b` = 0) %>%
  gather(Comparison, Difference, -(year:b) ) %>%
  separate(Comparison, c("First Val", "Second Val"), " - ")

那个returns一个data.frame像这样(这里只是头):

  year a b First Val Second Val Difference
1 2011 0 1         a          b         -1
2 2012 1 2         a          b         -1
3 2013 2 3         a          b         -1
4 2014 3 4         a          b         -1
5 2015 4 5         a          b         -1
6 2011 0 1         b          a          1

你可以这样画:

ggplot(forPlotting
       , aes(x = year, y = Difference)) +
  geom_point() + geom_line() +
  facet_grid(`First Val` ~ `Second Val`)

更大的问题是为什么你想这样做。我假设您已经知道将两组绘制成不同颜色的线条更容易可视化:

ggplot(df, aes(x=year, y=value, col = scenario)) +
  geom_point() + geom_line()

所以,我假设您有更复杂的数据——具体来说,有更多的列要比较。因此,这里有一种方法可以自动化(并简化)多个列的上述许多步骤。方法基本相同,但它使用 mutate_ 允许您传入一个包含您要创建的列的向量。

df <-
  data.frame(
    year = 2011:2015
    , a = 0:4
    , b = 1:5
    , c = 2:6
    , d = 3:7
  )

allContrasts <-
  outer(colnames(df)[-1]
        , colnames(df)[-1]
        , paste
        , sep = " - ") %>%
  as.character() %>%
  setNames(., .) %>%
  as.list()

forPlotting <-
  df %>%
  mutate_(.dots = allContrasts) %>%
  select(-(a:d)) %>%
  gather(Comparison, Difference, -year ) %>%
  separate(Comparison, c("First Val", "Second Val"), " - ") %>%
  filter(`First Val` != `Second Val`)

ggplot(forPlotting
       , aes(x = year, y = Difference)) +
  geom_point() + geom_line() +
  facet_grid(`First Val` ~ `Second Val`) +
  theme(axis.text.x = element_text(angle = 90))

给出这个:

为什么我不能不管这个?我就是太喜欢玩标准评价了。如果您有非解析列名(例如,带空格的东西),上述将失败。因此,这是一个包含此类列名的示例,显示了添加反引号以确保列正确解析。

df <-
  data.frame(
    year = 2011:2015
    , value = c(0:4, 1:5, 2:6, 3:7)
    , scenario = rep(c("Unit 1", "Exam 2"
                       , "Homework", "Final Exam")
                     , each = 5)
  ) %>%
  spread(scenario, value)

allContrasts <-
  outer(paste0("`", colnames(df)[-1], "`")
        , paste0("`", colnames(df)[-1], "`")
        , paste
        , sep = " - ") %>%
  as.character() %>%
  setNames(., .) %>%
  as.list()

forPlotting <-
  df %>%
  mutate_(.dots = allContrasts) %>%
  select_(.dots = paste0("-`", colnames(df)[-1], "`")) %>%
  gather(Comparison, Difference, -year ) %>%
  separate(Comparison, c("First Val", "Second Val"), " - ") %>%
  filter(`First Val` != `Second Val`) %>%
  mutate_each(funs(gsub("`", "", .)), `First Val`, `Second Val`)

ggplot(forPlotting
       , aes(x = year, y = Difference)) +
  geom_point() + geom_line() +
  facet_grid(`First Val` ~ `Second Val`) +
  theme(axis.text.x = element_text(angle = 90))

你想要下面这样的东西吗?

dflist <- split(df, df$scenario)
df <- rbind(merge(dflist$a, dflist$a, by='year'),
      merge(dflist$a, dflist$b, by='year'),
      merge(dflist$b, dflist$a, by='year'),
      merge(dflist$b, dflist$b, by='year'))
df$value <- df$value.x - df$value.y
ggplot(df, aes(x=year, y=value)) +
  geom_point() + geom_line() +
  facet_grid(scenario.x ~ scenario.y)