基于组或子组最大值对隐藏ggplot geom_bar中的条形图进行排序

cgfeq70w  于 2023-05-04  发布在  其他
关注(0)|答案(2)|浏览(130)

问题
我有一个分组条形图,我想根据一个子组的最大值对组进行排序。我读过很多类似的问题,但大多数都是在组的层面上处理排序,而不是子组的层面。下面是一个例子,看看我的意思。

复制

这里是一些关于七个人和他们的音乐偏好的数据。

set.seed(3)
df <- data.frame(person = c("John", "Sarah", "Alex", "Kate", "Oliver", "Emily", "Daniel"),
                 music_genre = rep(c("pop", "classical", "rap"), each = 7),
                 listens = sample(40:90, size = 21, replace = TRUE))

在软件包方面,我使用library(tidyverse)。这是一个简单的条形图,没有任何顺序。

ggplot(data=df) +
  geom_bar(aes(x=person,
               y=listens,
               fill=music_genre),
           stat="identity",
           position="dodge")

我所尝试的

我的目标是创建一个条形图,它按照特定music_genrelistens的数量排序persons,同时保留所有音乐流派的条形图。
我所知道的是如何在music_genre的所有值中按listens的数量对persons进行排序。但这不是我想要的。(顺便说一句,请注意古典音乐是如何在下面的情节中消失的,因为它与说唱音乐具有相同的价值。如果你知道如何解决这个问题,我很想知道。

ggplot(data=df) +
  geom_bar(aes(x=reorder(person, listens, max),
               y=listens,
               fill=music_genre,
               group=position),
           stat="identity",
           position="dodge")

另一件在很多帖子中讨论但没有解决我的问题的事情是如何对子组进行排序。如何在persons中排序。为此,我们可以向df添加一个新变量,然后按此变量分组。与前面的代码相比,这是通过包含mutate()调用的额外一行来完成的。

set.seed(3)
df <- data.frame(person = c("John", "Sarah", "Alex", "Kate", "Oliver", "Emily", "Daniel"),
                 music_genre = rep(c("pop", "classical", "rap"), each = 7),
                 listens = sample(40:90, size = 21, replace = TRUE)) %>%
  mutate(position = rank(-listens))

现在子组可以这样排序。(请再次注意,古典范畴在丹尼尔以理书中是如何消失的。)

ggplot(data=df) +
  geom_bar(aes(x=person,
               y=listens,
               fill=music_genre,
               group=position),
           stat="identity",
           position="dodge")

还可以组合组级排序和子组级排序。

ggplot(data=df) +
  geom_bar(aes(x=reorder(person, listens, max),
               y=listens,
               fill=music_genre,
               group=position),
           stat="identity",
           position="dodge")

这又一次没有解决我的问题。我提到这一点只是为了使我的问题更清楚,并表明我理解什么和不理解什么。

TL;DR

重申一下,我怎样才能得到一个根据特定组(music_genre)的y轴值(listens)的最大数量对x轴(persons)进行排序的图?

yx2lnoni

yx2lnoni1#

library(tidyverse)

df %>% 
  pivot_wider(id_cols = person, names_from = music_genre, values_from = listens) %>% 
  mutate(pos_id = rank(pop)) %>% ## genre that subgroups will be ordered based on
  pivot_longer(-c(person, pos_id), names_to = "music_genre", values_to = "listens") %>% 
  group_by(person) %>% 
  mutate(position = rank(-listens)) %>% 
 ggplot() +
  geom_bar(aes(x=reorder(person, pos_id, max),
               y=listens,
               fill=music_genre,
               group=position), ## use music_genre if you don't want to order subgroups
           stat="identity",
           position="dodge") +
  xlab("person")

数据:
structure(list(person = c("John", "Sarah", "Alex", "Kate", "Oliver", 
                           "Emily", "Daniel", "John", "Sarah", "Alex", 
                            "Kate", "Oliver", "Emily", "Daniel", "John", 
                            "Sarah", "Alex", "Kate", "Oliver", "Emily", "Daniel"), 
                music_genre = c("pop", "pop", "pop", "pop", "pop", "pop", "pop", 
                                "classical", "classical", "classical", "classical", 
                                "classical", "classical", "classical", "rap", "rap", 
                                "rap", "rap", "rap", "rap", "rap"), 
                listens = c(44L, 51L, 78L, 75L, 79L, 82L, 70L, 47L, 59L, 49L, 79L, 
                            87L, 79L, 47L, 76L, 41L, 68L, 83L, 84L, 44L, 79L)), 
          class = "data.frame", row.names = c(NA, -21L))
e4eetjau

e4eetjau2#

经过一番折腾,我找到了一种实现它的方法。
可以通过对人进行编码来实现期望的结果(即,在一个实施例中,将原始数据的排序子集(即,X轴上的分类变量)作为因子,然后通过仅包含感兴趣的排序类别(即,X轴上的分类变量)的原始数据的排序子集对因子水平进行排序。例如,“pop”)。

df <- df %>% 
  mutate(
    person = factor(
      person,
      levels = df %>% 
        filter(music_genre=="pop") %>% 
        arrange(listens) %>% 
        pull(person),
      ordered= T))

绘制分组条形图可以实现我们的目标:对于“pop”,从最高值到最低值对人进行排序。

ggplot(data=df) +
  geom_bar(aes(x=person,
               y=listens,
               fill=music_genre),
           stat="identity",
           position="dodge")

如果有人找到了更聪明的方法来做到这一点,特别是在ggplot()调用中工作的方法,我很想听听。

相关问题