使用ggplot2在堆叠条形图中对分类数据进行排序。

13

我有一个矩阵,其条目如下:

MilDis <- data.frame(
  hhDomMil = c(
    "HED", "ETB", "HED", "ETB", "PER", "BUM", "EXP", "TRA", "TRA", "PMA", "MAT",
    "MAT", "KON", "ETB", "PMA", "PMA", "HED", "BUM", "BUM", "HED", "PMA", "PMA",
    "HED", "TRA", "BUM", "EXP", "BUM", "PMA", "ETB", "MAT", "ETB", "ETB", "KON",
    "MAT", "TRA", "BUM", "BUM", "TRA", "TRA", "PMA", "PMA", "PMA", "MAT", "ETB",
    "TRA", "BUM", "TRA", "MAT", "BUM", "ETB", "TRA", "TRA", "BUM", "KON", "ETB",
    "ETB", "ETB", "BUM", "KON", "ETB", "ETB", "PMA", "TRA", "PER", "PER", "MAT",
    "HED", "KON", "TRA", "TRA", "TRA", "EXP", "TRA", "BUM", "MAT", "MAT", "TRA",
    "PMA", "HED", "PER", "TRA", "PER", "EXP", "PER", "BUM", "KON", "BUM", "ETB",
    "ETB", "TRA", "PER", "ETB", "KON", "KON", "BUM", "ETB", "BUM", "MAT", "BUM",
    "KON", "KON", "ETB", "MAT", "KON", "PER", "ETB", "ETB", "KON", "PMA", "PER",
    "HED", "HED", "PMA", "MAT", "PMA", "PER", "PMA", "TRA", "TRA", "MAT", "BUM",
    "BUM", "KON", "ETB", "ETB", "ETB", "PMA", "TRA", "TRA", "PMA", "PER", "KON",
    "PER", "BUM", "KON", "ETB", "ETB", "BUM", "TRA", "ETB", "PMA", "HED", "MAT",
    "TRA", "BUM", "PMA", "BUM", "ETB", "TRA", "TRA", "TRA", "PER", "EXP", "HED",
    "BUM", "EXP", "HED", "BUM", "MAT", "DDR", "BUM", "MAT", "KON", "HED", "HED",
    "TRA", "BUM", "PMA", "PMA", "PMA", "KON", "KON", "MAT", "ETB", "MAT", "TRA",
    "MAT", "ETB", "ETB", "TRA", "MAT", "ETB", "TRA", "HED", "BUM", "MAT", "TRA",
    "PMA", "BUM", "BUM", "EXP", "ETB", "EXP", "EXP", "MAT", "TRA", "KON", "BUM",
    "BUM", "HED"
  ),
  kclust = c(
    1L, 2L, 15L, 4L, 5L, 6L, 5L, 7L, 8L, 5L, 6L, 5L, 11L, 6L, 5L,
    1L, 9L, 10L, 2L, 1L, 9L, 8L, 4L, 11L, 14L, 5L, 8L, 11L, 12L,
    5L, 5L, 14L, 15L, 2L, 10L, 6L, 8L, 4L, 6L, 8L, 14L, 14L, 16L,
    10L, 5L, 1L, 12L, 17L, 12L, 16L, 16L, 5L, 10L, 14L, 8L, 19L,
    5L, 4L, 4L, 14L, 2L, 14L, 9L, 7L, 1L, 14L, 4L, 15L, 18L, 16L,
    9L, 14L, 6L, 14L, 12L, 11L, 4L, 7L, 8L, 12L, 9L, 16L, 2L, 6L,
    15L, 1L, 1L, 3L, 14L, 5L, 5L, 9L, 14L, 6L, 5L, 14L, 15L, 2L,
    14L, 2L, 1L, 8L, 5L, 10L, 1L, 1L, 16L, 5L, 2L, 9L, 9L, 1L, 12L,
    10L, 1L, 4L, 1L, 9L, 8L, 8L, 5L, 10L, 1L, 10L, 2L, 6L, 15L, 2L,
    2L, 10L, 5L, 6L, 10L, 19L, 19L, 6L, 5L, 6L, 7L, 7L, 8L, 5L, 16L,
    5L, 6L, 6L, 1L, 10L, 12L, 4L, 7L, 19L, 7L, 8L, 16L, 10L, 5L,
    16L, 12L, 7L, 7L, 19L, 4L, 6L, 1L, 15L, 7L, 8L, 16L, 4L, 10L,
    15L, 11L, 10L, 1L, 10L, 17L, 1L, 2L, 1L, 14L, 8L, 8L, 14L, 10L,
    8L, 6L, 6L, 8L, 5L, 7L, 5L, 1L, 5L, 7L, 9L, 2L, 1L, 9L, 14L
  ),
  order = c(
    9, 1, 9, 1, 3, 7, 10, 5, 5, 2, 8, 8, 4, 1, 2, 2, 9, 7, 7, 9, 2, 2, 9, 5, 7,
    10, 7, 2, 1, 8, 1, 1, 4, 8, 5, 7, 7, 5, 5, 2, 2, 2, 8, 1, 5, 7, 5, 8, 7, 1, 5,
    5, 7, 4, 1, 1, 1, 7, 4, 1, 1, 2, 5, 3, 3, 8, 9, 4, 5, 5, 5, 10, 5, 7, 8, 8, 5,
    2, 9, 3, 5, 3, 10, 3, 7, 4, 7, 1, 1, 5, 3, 1, 4, 4, 7, 1, 7, 8, 7, 4, 4, 1, 8,
    4, 3, 1, 1, 4, 2, 3, 9, 9, 2, 8, 2, 3, 2, 5, 5, 8, 7, 7, 4, 1, 1, 1, 2, 5, 5,
    2, 3, 4, 3, 7, 4, 1, 1, 7, 5, 1, 2, 9, 8, 5, 7, 2, 7, 1, 5, 5, 5, 3, 10, 9, 7,
    10, 9, 7, 8, 6, 7, 8, 4, 9, 9, 5, 7, 2, 2, 2, 4, 4, 8, 1, 8, 5, 8, 1, 1, 5, 8,
    1, 5, 9, 7, 8, 5, 2, 7, 7, 10, 1, 10, 10, 8, 5, 4, 7, 7, 9
  )
)

我想创建一个类似于这个的堆积条形图 Barplot

唯一的问题是,我希望堆栈的顺序与矩阵中的顺序(ETB、PMA、PER、KON、TRA、DDR、BUM、MAT、HED、EXP)相匹配,并且我还有一些美学问题。我在这里搜索了解决方案,但没有一个排序建议适用于我... :-\

  1. 如何绘制这样一个有序的图?
  2. 如何设置x轴,使每个条形图都“在”一个数字上?
  3. 如何分离条形图 - 在这里我尝试使用白色边框...?
  4. 如何打印x中的所有kclust数字?

非常感谢您的帮助! Dominik


更新

这是我用来绘制图形的代码:

mycols <- c('#FFFD00', '#97CB00', '#3168FF', '#FF0200', '#FB02FE', \
'#CCFCCC', '#FE9900', '#98CBF8', '#00CCFF', '#00FD03') # Set milieu colors


ggplot(MilDis) +
 geom_bar(aes(kclust, fill=factor(hhDomMil), \
 colour=mycols), position='fill', binwidth=1, colour='white') +
 scale_fill_manual(values = mycols)

更新2:

这是我现在的做法:

    mycols <- c('#3168FF', '#00CCFF', '#98CBF8', '#CCFCCC', '#00FD03',\
   '#97CB00', '#FFFD00', '#FE9900', '#FB02FE', '#FF0200') # Set milieu colors
   
    ggplot(MilDis) +
      geom_bar(aes(factor(kclust), fill=reorder(hhDomMil,order)),\
      position='fill') +
      scale_fill_manual(values = mycols)

得到这个结果:

Image

感谢大家的帮助!


你能否发布一下你用来生成这里展示的图形的ggplot代码?这将节省一些时间,以便进行你所请求的修改(除了排序,@Gavin Simpson已经处理过了)... - Ben Bolker
每个问题应该只提出一个问题 - 这样更容易搜索和找到答案。 - Gavin Simpson
@Ben:我刚刚更新了我的帖子。 - Dominik
@Dominik 为什么?我已经回答了1,甚至不需要绘图代码。2、3和4只需要将“kclust”强制转换为因子 - 目前您正在使用连续变量,因此x轴上的刻度是连续的。 - Gavin Simpson
您可以链接问题以显示它们之间的关系。总体而言,您所写的没有什么问题,我只是想指出,为了将来的参考,最好每个帖子只发布一个问题。正如我所说,这有助于SO成为不仅对提问者有帮助的问答社区。如果问题具有聚焦性和特定性,它将帮助在SO上搜索的用户深入了解与其问题相关的Q&A。 - Gavin Simpson
显示剩余3条评论
3个回答

12

在将数据传递给ggplot()之前,通过正确格式化数据来解决这个问题非常容易。关键是要明确设置hhDomMil因子的级别。假设您的数据在dat中:

dat <- transform(dat, hhDomMil = factor(hhDomMil,
                                        levels = c("ETB", "PMA", "PER", "KON",
                                                   "TRA", "DDR", "BUM", "MAT",
                                                   "HED", "EXP")))

这会将hhDomMil作为因子就地修改dat中固定,并且将级别按照您指定的顺序排列:

> head(dat$hhDomMil)
[1] HED ETB HED ETB PER BUM
Levels: ETB PMA PER KON TRA DDR BUM MAT HED EXP

注意当R将hhDomMil强制转换为因子时发生了什么:

> head(factor(as.character(dat$hhDomMil)))
[1] HED ETB HED ETB PER BUM
Levels: BUM DDR ETB EXP HED KON MAT PER PMA TRA

默认情况下,级别是按字母顺序排序的,这就是为什么绘图结果与您显示的相同。

我能给出的最好建议是,首先正确格式化数据,然后再尝试绘图 - 不要依赖自动或即时转换来使其符合您的要求;不可避免地它不会是您想要的。


12

我看到你的数据框中有一个order列,据我推断这是你的顺序。因此,你可以简单地执行以下操作。

我发现您的数据框中有一个order列,我猜这是您的排序列。 因此,您可以直接执行以下操作。

p0 = qplot(factor(kclust), fill = reorder(hhDomMil, order), position = 'fill', 
       data = df1)

以下是代码中处理你提出问题的要点:

  1. 如何绘制这样的有序图形?使用 reorder
  2. 如何设置 x 轴,以使每个柱都对应一个数字?使用 factor(kclust)
  3. 如何将各个柱分开显示?
  4. 如何在 x 中打印所有的 kclust 数字?使用 factor(kclust)

我记得你之前的问题中提到过 hhDomMil 对应不同的组,而我认为你的排序遵循着这些组的顺序。如果是这样,你可以利用这些信息选择一个更容易跟踪图表的颜色调色板。下面是一种方法。

mycols = c(brewer.pal(3, 'Oranges'), brewer.pal(3, 'Greens'), 
           brewer.pal(2, 'Blues'), brewer.pal(2, 'PuRd'))

p0 + scale_fill_manual(values = mycols)

在这里输入图片描述


非常感谢您的解决方案!这正是我在寻找的。而且您的假设是绝对正确的,它们以所描述的方式相对应。 - Dominik
如果聚类编号没有任何意义,那么我会重新排列这个图表,使得聚类按照它们所包含的元素数量进行排列。或者你也可以根据它们所包含的组数来排列聚类。 - Ramnath
聚类对应邻域设置。但是所有环境都在所有簇中。在显示的示例中,并不是所有数据点,因为在此处发布它们会太大... 但您的想法很好,您有关于update2中的绘图的想法吗? - Dominik

7
如果您将hhDomMil重新设置为如下因子:
o<-c("ETB" "PMA" "PER" "KON" "TRA" "DDR" "BUM" "MAT" "HED" "EXP")
d$hh<-factor(d$hhDomMil,levels=o)

那么您的图表将按您喜欢的顺序呈现:
ggplot(d,(aes(x=kclust, fill=hh))) +geom_bar(position="fill")

我喜欢这个解决方案,因为 a) 它简洁明了,b) 它也适用于非 ggplot 的问题。 - IRTFM
像Gavins的解决方案一样,这是一个很好的通用解决方案。 - Dominik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接