【问题标题】:create clearly distinguishable line plot of pairs of variables创建变量对的清晰可区分的线图
【发布时间】:2018-12-20 01:38:38
【问题描述】:

我有以下数据框:

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. 这些对必须易于区分,即必须易于从regressionregression_unanswered对应的两行中辨别出rr_unanswered对应的两行;
  2. 在每一对中,必须很容易通过肉眼将unanswered 变量与另一对区别开来。
  3. 该方法必须扩展到更多对。在这个简单的例子中,我有 3 对:在我的实际情况中,我可能有 10 个或更多。

我想通过对每对使用相同的颜色来实现这一点更具视觉吸引力。无论如何,我的问题是我什至无法实现这个简单的想法。我试过了

tall_unanswered <- foobar %>% select(ends_with("unanswered"), month) %>% 
  gather(key = tag, value = count, -month)
tall_total <- foobar %>% select(-ends_with("unanswered")) %>% 
  gather(key = tag, value = count, -month)
p <- ggplot(tall_total, aes(x = month, y = count, color = tag)) +
  geom_line() +
  geom_line(data = tall_unanswered, linetype = "dashed")

但这不起作用:每对的颜色都不一样,所以我无法实现目标 1(每对必须很容易与其他人区分开来)。

【问题讨论】:

    标签: r ggplot2 dplyr tidyr


    【解决方案1】:

    我会通过将所有列收集成一个长格式然后根据这些列名创建变量以映射到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))
    

    您可以根据需要删除或更改图例以满足您的目的。

    更复杂的分割方式:separate()

    正如@Henrik 指出的那样,您可以通过正则表达式使用前瞻来拆分“未回答”一词前面的下划线。这避免了我的解决方法sub() 并节省了一步。

    这部分代码如下所示:

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

    【讨论】:

    • 为了节省一些输入,您可以在separate:separate(tag, into = c("name", "answered"), sep = "_(?=[unanswered])", fill = "right") 中使用前瞻...并使用replace 而不是ifelse:mutate(answered = replace(answered, is.na(answered), "answered"))。我认为不需要group aesggplot(foolong, aes(x = month, y = count, color = name, linetype = answered)) + geom_line()。干杯
    • 很好,但是“已回答的问题没有信息表明已回答[..]”这是因为它们不是已回答的问题,它们是total 个问题,即已回答 + 未回答(您可能已经注意到数据框名称:tall_unansweredtall_total,而不是 tall_answered)。无论如何,我可以很容易地解决这个问题。你有机会美化这个传说吗?也许让它占据整个图片空间的更少,或者把它放在 inside 绘图画布;-) 我知道这不是原始问题的一部分,但对于像你这样的专家来说应该很容易.. .
    • @DeltaIV Look-ahead 是一个正则表达式术语。与其重申聪明人已经写过的东西,不如搜索正则表达式教程,例如here
    • @DeltaIV 您可以分别使用theme() 元素legend.positionlegend.direction 将图例移动到绘图内部或另一侧,或使其水平。如果您在处理图例时遇到特定问题,我建议您提出一个新问题。
    • @Henrik 太棒了!我知道有一种合乎逻辑的方法来拆分昨晚没有出现的变量。我一直专注于拆分“最后一个”下划线并遇到问题,而不是考虑使用“未回答”之前的下划线。
    猜你喜欢
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 2019-03-27
    • 2023-02-25
    • 2015-12-12
    • 2014-04-10
    相关资源
    最近更新 更多