【问题标题】:reorder barchart by sum of bar segments with ggplot/plyr使用 ggplot/plyr 通过条形图的总和对条形图重新排序
【发布时间】:2015-05-19 22:57:09
【问题描述】:

我需要以下堆叠条形图中的 11 个条形按每个条形的前两个段的总和重新排序,即按图中的(红色+绿色)段排序。

> dput(q1m.bl)
structure(list(ItemA = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 
4L, 1L, 2L, 3L, 4L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 
1L, 2L, 3L, 4L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 
2L, 3L, 4L), .Label = c("sehr wichtig", "wichtig", "unwichtig", 
"keine Angabe"), class = "factor"), ItemQ = structure(c(1L, 1L, 
1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 
5L, 6L, 6L, 6L, 6L, 7L, 7L, 7L, 7L, 8L, 8L, 8L, 9L, 9L, 9L, 9L, 
10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L), .Label = c("PUSHERS_AA", 
"PUSHERS_COM", "PUSHERS_BED", "PUSHERS_SEC", "PUSHERS_STAB", 
"PUSHERS_COST", "PUSHERS_INNO", "PUSHERS_VAL", "PUSHERS_INDEP", 
"PUSHERS_STDS", "PUSHERS_SRC"), class = "factor"), Counts = c(1L, 
3L, 4L, 1L, 3L, 3L, 2L, 1L, 4L, 2L, 2L, 1L, 3L, 5L, 1L, 1L, 1L, 
6L, 1L, 5L, 1L, 2L, 1L, 1L, 1L, 6L, 1L, 2L, 6L, 1L, 2L, 4L, 2L, 
1L, 3L, 3L, 2L, 1L, 2L, 1L, 5L, 1L), blpos = c(0.111111111111111, 
0.444444444444444, 0.888888888888889, 1, 0.333333333333333,   0.666666666666667, 
0.888888888888889, 1, 0.444444444444444, 0.666666666666667, 0.888888888888889, 
1, 0.333333333333333, 0.888888888888889, 1, 0.111111111111111, 
0.222222222222222, 0.888888888888889, 1, 0.555555555555556, 0.666666666666667, 
0.888888888888889, 1, 0.111111111111111, 0.222222222222222, 0.888888888888889, 
1, 0.222222222222222, 0.888888888888889, 1, 0.222222222222222, 
0.666666666666667, 0.888888888888889, 1, 0.333333333333333, 0.666666666666667, 
0.888888888888889, 1, 0.222222222222222, 0.333333333333333, 0.888888888888889, 
1)), .Names = c("ItemA", "ItemQ", "Counts", "blpos"), row.names = c(NA, 
-42L), class = "data.frame")

剧情...

ggplot(q1m.bl, aes(x = ItemQ, y = Counts, fill = ItemA)) + 
geom_bar(stat="identity", position="fill") + 
geom_text(aes(y = blpos, label = Counts), hjust = 1) +
theme(axis.text.x=element_text(angle=90, hjust = 0), text = element_text(size=10)) +
coord_flip()

呃,没有足够的代表点来嵌入图像。带来不便敬请谅解。剧情在这里:http://i.stack.imgur.com/am0Ud.png

我玩过安排(),在检查了数据框本身之后,我认为下面的排序应该可以解决问题。 (注意:blpos 表示“条形标签位置”,是图中各种数字的位置。)但是绘制这个“排序”数据框会导致与上面相同的图。我不明白要更改哪些信息来更改 ItemQ 列的绘图顺序。

q1m.bl.s <- arrange(q1m.bl, ItemA, desc(blpos))
ggplot(q1m.bl.s, ....

无论如何,最好的方法是什么?我应该在绘图之前操作 df(使用 ddply/arrange/reorder/etc.)吗?因为我倾向于认为这是一个演示问题,应该在 inside ggplot 中完成。这还重要吗?我在 SO 上发现的“ggplot 有序条形图”问题似乎同时使用了这两种方法;但是我发现没有一个是指堆叠条 segments 并使用因子数据......因此这个新问题。

非常感谢您对我的启发!

【问题讨论】:

    标签: r ggplot2 plyr geom-bar


    【解决方案1】:

    这完全是为了重新排序ItemQ 变量的因子水平。

    d <- subset(q1m.bl, ItemA %in% c("sehr wichtig", "wichtig"))
    totals <- aggregate(d$Counts, list(ItemQ = d$ItemQ), sum)
    ItemQ.order <- as.character(totals[order(-totals$x), ]$ItemQ)
    q1m.bl$ItemQ <- factor(q1m.bl$ItemQ, levels = ItemQ.order)
    

    然后你应该能够完全按照你提供的代码运行它,它会产生这个:

    编辑(digisus):konvas,我只是重新添加您的第一个答案,显示 ddply 的使用,因为即使我对它感到不舒服/不完全理解它,我相信其他人可以从中受益。 :-) 所以,在你的允许下,我在这里重新发布:

    library(plyr)
    ItemQ.order <- q1m.bl %>%
      group_by(ItemQ) %>% 
      filter(ItemA %in% c("sehr wichtig", "wichtig")) %>% 
      summarise(total = sum(Counts)) %>%
      arrange(-total) %>% 
      select(ItemQ) %>%
      unlist %>%
      as.character
    
    q1m.bl$ItemQ <- factor(q1m.bl$ItemQ, levels = ItemQ.order)
    

    【讨论】:

    • @konvas,感谢您的快速回复!不幸的是,我得到 Error: could not find function "%>%" -- 实际上我并不熟悉这个 "%>%" 函数/符号。 (同样使用 %in% 虽然我可以猜测它可能意味着什么。)如果你能详细说明一下,那将对我有很大帮助。谢谢!
    • 该操作符是 dplyr/magrittr 包的一部分,用于链接命令的简单语法方式。例如,您有一个包含两个变量的函数f。然后你可以写a %&gt;% f(b),而不是写f(a,b)。当您有更多功能时,这将变得很有用,例如 g(f(a, b), c) 变为 a %&gt;% f(b) %&gt;% g(c) 等等...有关更多信息,请参阅帮助文件。我只是用它来以所需的顺序获取ItemQ 的元素。如果您更熟悉其他方法(例如aggregate 等),请随意使用这些方法。
    • 谢谢@konvas。我将安装这些软件包并检查它们。我只是想知道...为什么看似简单的任务在 R 中经常“爆炸”到如此复杂。:-/
    • 跟进。我已经卡在安装:错误:依赖项'lazyeval'不适用于包'dplyr'。感谢您的努力 konvas,但除非有人能指出我更简单的解决方案,否则我必须放弃。事实上,由于时间限制,我将不得不恢复到(喘气)电子表格应用程序。我花了超过 1 周的时间才得到 5 个条形图,但我什至没有做到这一点。很抱歉把这个丢在这里,这非常令人沮丧。尽管如此,还是感谢您抽出宝贵的时间。 :-)
    • 非常感谢@konvas,非常感谢! :-)
    【解决方案2】:
    library(ggplot2)
    
    fac_ord <- function(seed){
      set.seed(seed)
      return(sample(letters[1:4]))
    }
    
    # this seed simulates arbitrary sortings
    seed <- 2
    fac_ord(seed)
    
    val = c(1,2,3,4,2,2,2,2)
    fac = factor(c("a","b","c","d","a","b","c","d"), 
                 levels=fac_ord(seed), 
                 labels=fac_ord(seed), 
                 ordered=FALSE)
    dif = c(rep("x",4),rep("y",4))
    
    df  = data.frame(val = val, fac = fac)
    
    ggplot(df, aes(x=fac, y=val, fill=dif)) + 
      geom_bar(stat="identity") + 
      labs(title = sprintf("seed = %d / %s", seed, paste(fac_ord(seed),collapse=",")))
    

    如示例所示 - ggplot 将在图中使用与 fac 相同的顺序作为 fac 的内部顺序。因此,要影响绘制的顺序,您必须编写一个返回预期顺序的函数 - 取决于任何事实和值 - 并使用它来创建因子 fac - 然后使用这个正确排序的因子进行绘图。

    也可以通过应用reorder() 对因子的水平进行重新排序来达到预期结果。

    【讨论】:

    • 感谢您努力解释核心逻辑。我会再仔细考虑一下……我觉得这也有助于更好地理解@konvas 的答案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2022-08-23
    相关资源
    最近更新 更多