使用R中的给定数据创建水平“堆积”条形图

时间:2014-09-18 07:28:18

标签: r ggplot2 bar-chart

我正在尝试在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的特定颜色,直到相应的“访问日”。
  4. 例如,对于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,酒吧的那部分应该是绿色的。

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

    感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:2)

我很难看到你想要的东西。但是,这是我的建议。你想要两件事。一个是您需要特定剂量的特定颜色。另一个是您希望按特定顺序拥有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()

enter image description here

答案 1 :(得分: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'))

bar plot

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

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'))

bar plot 2