创建变量对的清晰可辨的折线图

时间:2018-07-11 22:51:30

标签: r ggplot2 dplyr tidyr

我有以下数据框:

library(dplyr)
library(tidyr)
library(ggplot2)

foobar <- structure(list(month = structure(c(1477872000, 1480464000, 1483142400, 
1485820800, 1488240000, 1490918400, 1493510400, 1496188800, 1498780800, 
1501459200, 1504137600, 1506729600, 1509408000, 1.512e+09, 1514678400, 
1517356800, 1519776000, 1522454400, 1525046400, 1527724800, 1530316800
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), r = c(283L, 
298L, 277L, 231L, 276L, 323L, 242L, 255L, 208L, 289L, 284L, 263L, 
280L, 278L, 269L, 288L, 255L, 324L, 339L, 355L, 300L), r_unanswered = c(133L, 
139L, 106L, 85L, 132L, 141L, 89L, 110L, 80L, 142L, 174L, 159L, 
146L, 162L, 153L, 161L, 142L, 174L, 211L, 208L, 194L), regression = c(260L, 
278L, 249L, 242L, 301L, 349L, 249L, 309L, 256L, 280L, 326L, 276L, 
299L, 322L, 235L, 281L, 256L, 293L, 356L, 307L, 279L), regression_unanswered = c(102L, 
119L, 92L, 107L, 119L, 126L, 108L, 132L, 89L, 141L, 199L, 148L, 
161L, 160L, 125L, 159L, 137L, 139L, 208L, 177L, 162L), machine_learning = c(208L, 
190L, 176L, 208L, 221L, 265L, 204L, 215L, 251L, 283L, 314L, 257L, 
250L, 290L, 240L, 290L, 275L, 295L, 292L, 316L, 324L), machine_learning_unanswered = c(64L, 
67L, 62L, 86L, 78L, 76L, 67L, 67L, 90L, 128L, 155L, 106L, 125L, 
132L, 125L, 143L, 132L, 159L, 159L, 158L, 191L)), row.names = c(NA, 
-21L), class = c("tbl_df", "tbl", "data.frame"))
> glimpse(foobar)
Observations: 21
Variables: 7
$ month                       <dttm> 2016-10-31, 2016-11-30, 2016-12-31, 2...
$ r                           <int> 283, 298, 277, 231, 276, 323, 242, 255...
$ r_unanswered                <int> 133, 139, 106, 85, 132, 141, 89, 110, ...
$ regression                  <int> 260, 278, 249, 242, 301, 349, 249, 309...
$ regression_unanswered       <int> 102, 119, 92, 107, 119, 126, 108, 132,...
$ machine_learning            <int> 208, 190, 176, 208, 221, 265, 204, 215...
$ machine_learning_unanswered <int> 64, 67, 62, 86, 78, 76, 67, 67, 90, 12...

我想将所有非month变量成对分组(例如rr_unanswered),并与month同时绘制所有变量柱。我想实现三个目标:

  1. 这些对必须易于区分,即必须容易地从与r和{对应的两条线中辨别与r_unansweredregression对对应的两条线{1}};
  2. 在每一对中,必须容易通过肉眼辨别regression_unanswered变量与另一对变量。
  3. 该方法必须扩展到更多对。在这个简单的示例中,我有3对:在我的实际情况下,我可能有10对或更多。

我正在考虑通过在每对中使用相同的颜色,并在每对内部使用unanswered变量绘制为虚线来实现此目的,但是我愿意接受其他建议,如果您认为它们的话可能在视觉上更具吸引力。无论如何,我的问题是我什至无法实现这个简单的想法。我尝试过

unanswered

但是它不起作用:每对颜色都不相同,因此我无法实现目标1(每对颜色必须易于与其他颜色区分开)。

enter image description here

1 个答案:

答案 0 :(得分:3)

我将通过将所有列收集为长格式,然后基于这些列名称创建变量以映射到colorlinetype来做到这一点。您可以使用tidyr::separate()完成后一项任务。

我发现您的特殊情况要困难一些,因为某些标记名称包含下划线,而不仅仅是“未答复”之前的标记。因此,我首先用"_unanswered"替换了".unanswered",以便可以在句点而不是下划线上分隔“标记”。这将创建两个新列,一列用于颜色(基于标记名称),一列用于线型(基于已回答或未回答)。回答的问题没有信息说明已回答,因此我在声明中添加了ifelse()语句。

这是数据操作:

foolong = foobar %>%
    gather(tag, count, -month) %>%
    mutate(tag = sub("_unanswered", ".unanswered", tag)) %>%
    separate(tag, into = c("name", "answered"), sep = "\\.", 
             remove = FALSE, fill = "right") %>%
    mutate(answered = ifelse(!is.na(answered), "unanswered", "answered"))

然后可以通过将颜色和线型映射到新变量来绘制图。

ggplot(foolong, aes(x = month, y = count, 
                    color = name) +
    geom_line( aes(linetype = answered))

enter image description here

您可以根据需要删除或更改图例。

更复杂的通过split()进行拆分的方法

正如@Henrik指出的那样,您可以通过正则表达式使用预读功能仅对下划线加上“ unanswered”一词进行拆分。这避免了我的解决方法sub(),并节省了一个步骤。

那部分代码如下:

foobar %>%
     gather(tag, count, -month) %>%
     separate(tag, into = c("name", "answered"), sep = "_(?=[unanswered])", 
              remove = FALSE, fill = "right")