【问题标题】:Creating Horizontally 'Stacked' Bar Chart with given data in R在 R 中使用给定数据创建水平“堆叠”条形图
【发布时间】:2014-11-12 10:36:43
【问题描述】:

我正在尝试在 R 中创建一个水平“堆叠”条形图。我正在绞尽脑汁,因为我读过的大多数示例并没有完全满足我的需求。以下是一些示例数据:

pat3 <- pat2[c("id", "visitday","dose")] #given data.
pat3

    id    visitday dose
7   11558     1.87 3850
8   11558    41.14 3850
9   11558    95.37 3800
10  11558   132.77 3800
28  11559     1.87 3850
29  11559    56.10 3800
30  11559    95.37 3800
31  11559   132.77 3800
32  11559   173.91 3800
46  11560     1.87 3850
47  11560    69.19 3794
48  11560   108.46 3794
49  11560   147.73 3794
50  11560   187.00 3794
51  11560   226.27 3794
  1. 在 y 轴上,我需要按升序排列的唯一“id”。
  2. x 轴将是一个连续的刻度,其中水平条将按升序“堆叠”到每个“访问日”。
  3. “剂量”是从时间 0 到下一个“访问日”消耗的液体量度。剂量将水平“堆叠”,其中给定的剂量将是每个 ID 条上的特定颜色,直到相应的“访问日”。

例如,对于 ID=115588,从访问日 0 到 1.87,他们消耗了 3850 剂,因此他们的条形图在条形图上从 0 到 1.87 为蓝色。到 41.14 访问日,他们仍然消耗了另一剂 3850,因此从 1.88 到 41.14,他们的条形图仍然是蓝色的。但是从 41.15 到 95.37,他们将服用 3800 的新剂量,他们的酒吧现在将变成不同的颜色,比如红色。访问日 95.38 - 132.77 也是如此,因为仍然是相同的 3800 剂量。

因此对于这个 ID=115588,我们应该看到一个蓝色的条形图,剂量 = 3850,从访问日 0 到 41.14,“堆叠”在上面,将是红色,剂量=3800,从访问日 41.15 到 132.77 .

这就是我现在的位置:

pat3 <- pat2[c("id", "visitday","dose")] #get data.

diff2 <- function(x) diff(c(0, x))
pat3$diffday <- c(unlist(t(aggregate(visitday~id, pat3, diff2)[, -1])))

pat3 #check diffday

w <- reshape(pat3, 
         timevar = "id",
         idvar = c("dose","visitday"),
         direction = "wide")

drops <- c("visitday")
w2 <- w[,!(names(w) %in% drops)]

w2[is.na(w2)] <- 0
w3 <- data.matrix(w2)

barplot(w3, horiz=T)

如您所见,我一直坚持如何对每种剂量的颜色进行分类,同样,只要所有服用这些剂量的患者一致,剂量就可以是任何颜色。因此,如果有人服用剂量=3850,则其条形部分应为蓝色,如果有人服用剂量=3800,则其条形部分应为红色,如果有人服用剂量=3794,则条形部分应为绿色.

我还需要从图表中删除“剂量”栏,因为我保留它只是为了帮助对每个剂量组的颜色进行分类,但甚至没有达到那么远...

感谢任何帮助。谢谢!

【问题讨论】:

    标签: r ggplot2 bar-chart


    【解决方案1】:

    我很难看出你想要什么。但是,这是我的建议。你想要两件事。一是您想要特定数量的剂量的特定颜色。另一个是您希望拥有特定顺序的 ID。我做了以下事情。

    mydf$id <- factor(mydf$id)
    mydf$id <- factor(mydf$id, levels = c("11560", "11559", "11558"))
    
    p <- ggplot(data = mydf, aes(x = id, y = dose, fill = factor(dose)))+
         geom_bar(stat="identity") +
         scale_fill_manual(values = c("green", "red", "blue"))
    

    正如 Paulo 所建议的,您可以在 y 轴上设置访问日,但我在轴上选择了 Dose。由于您在每个时期都有不同的访问日,我认为在酒吧显示访问日会很好。 foo$day 是一列,包括您数据集中的访问日期。

    #After reordering the factor level, I need to change the order of visit day
    ana <- as.matrix(mydf$visitday)
    ana <- ana[c(10:15,5:9,1:4)]
    
    # foo will be used to add texts (visit day) in ggplot.
    foo = ggplot_build(p)$data[[1]]
    foo$day <- ana
    
    p + 
    annotate(x = foo$x, y = foo$ymax, label = foo$day, geom="text", size=3) +
    xlab("ID") +
    ylab("Dose") +
    guides(fill=guide_legend(title="Dose")) +
    coord_flip()
    

    【讨论】:

    • 非常感谢!在我发布了这个问题之后,我实际上一直在努力解决这个问题,并且我已经了解了你们俩。很抱歉我的冗长问题,因为我正在努力在凌晨试图解决这个问题。你们俩都帮了大忙!我还在上面询问了 Paulo 如何反转 ID 的顺序,以便 11558 在顶部,11559 在下一个,然后 11560 在底部。这就是我现在所处的位置。
    • @user3542131 很高兴听到这两个想法都对您有所帮助。阅读您的评论后,我修改了我的答案。您只需要更改因子顺序的顺序,您可以在脚本的前两行中看到。希望这对你有用。
    【解决方案2】:

    或者类似的东西? 我将在这里打破剂量只是为了更好地了解被映射的变量。在这种情况下,无需添加新列。

    df$cdose <- cut(df$dose, breaks = c(0,3794,3800,3850),
                    labels = c('green', 'red', 'blue'))
    
          id visitday dose cdose
    7  11558     1.87 3850  blue
    8  11558    41.14 3850  blue
    9  11558    95.37 3800   red
    10 11558   132.77 3800   red
    28 11559     1.87 3850  blue
    29 11559    56.10 3800   red
    30 11559    95.37 3800   red
    31 11559   132.77 3800   red
    32 11559   173.91 3800   red
    46 11560     1.87 3850  blue
    47 11560    69.19 3794 green
    48 11560   108.46 3794 green
    49 11560   147.73 3794 green
    50 11560   187.00 3794 green
    51 11560   226.27 3794 green
    

    画出来

    library(ggplot2)
    ggplot(aes(y=visitday, x=id, fill = cdose), data = df) +
      geom_bar(stat = 'identity') +
      coord_flip() +
      scale_fill_manual('Dose', values = c('green', 'red', 'blue'))
    

    事实上,考虑到剂量正好这三个值,这样做会更容易:

    ggplot(aes(y=visitday, x=id, fill = factor(dose)), data = df) +
      geom_bar(stat = 'identity') +
      coord_flip() +
      scale_fill_manual('Dose', values = c('green', 'red', 'blue'),
                        labels = c('green:3794', 'red:3800', 'blue:3850'))
    

    【讨论】:

    • 这太棒了!谢谢你。如何重新排列 ID 号,使 ID=11558 位于顶部,然后 11559 和 11560 位于底部?
    • 顺便说一句...我也想给你一个“绿色复选标记”,但我知道我只能选择一个解决方案。
    • @user3542131 好的。为您的问题选择最好的!这就是想法。我会改变我的以解决您的重新排序问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2016-10-29
    • 2021-08-07
    • 1970-01-01
    相关资源
    最近更新 更多