Мне ужасно не удается разобраться в группировке в ggplot geom_bar.

У меня есть фиктивная структура фрейма данных, хотя реальный фрейм данных значительно больше:

df<-data.frame(id=1:12,
    count=c(12,5,33,6,43,12,8,56,14,43,36,32),
    name=c("A","A","A","B","B","B","B","B","B","C","C","D"),
    stringsAsFactors=F)

Используя либо макет, либо в данном случае реальный фрейм данных, я получаю график вроде

ggplot(df, aes(x=id,y=count)) + geom_bar(stat="identity")

enter image description here

Это отображает все в правильном порядке (как указано во фрейме данных), однако по оси x, а не числовых значений id , я хотел бы использовать name как группа: «A» для первых трех значений, «B» - для шести, «C» для следующих двух и «D» для конечного значения - или имена собственные в случае полного набора данных.

Я чувствую, что это должно быть довольно легко, если мой фрейм данных отформатирован правильно. Любая помощь, очень признательна.

0
Anthony Nash 17 Сен 2018 в 23:54

2 ответа

Лучший ответ

Мы можем указать метки в функции scale_x_discrete.

library(ggplot2)

df<-data.frame(id=1:12,
               count=c(12,5,33,6,43,12,8,56,14,43,36,32),
               name=c("A","A","A","B","B","B","B","B","B","C","C","D"),
               stringsAsFactors=F)

ggplot(df, aes(x = factor(id), y = count)) + 
  geom_bar(stat="identity") +
  scale_x_discrete(name = "name", labels = df$name)

enter image description here

Если вам нужна только одна метка для каждой группы, вы можете сделать следующее, чтобы метка оставалась на первой панели каждой группы.

library(dplyr)

df2 <- df %>%
  group_by(name) %>%
  mutate(name2 = ifelse(row_number() > 1, "", name)) %>%
  ungroup()

ggplot(df, aes(x = factor(id), y = count)) + 
  geom_bar(stat = "identity") +
  scale_x_discrete(name = "name", labels = df2$name2) +
  theme(axis.ticks.x = element_blank())

enter image description here

Или используйте facet_grid.

ggplot(df, aes(x = factor(id), y = count)) + 
  geom_bar(stat = "identity") +
  scale_x_discrete(name = "id") +
  facet_grid(. ~ name, space = 'free_x', scales = 'free_x')

enter image description here

4
www 17 Сен 2018 в 21:34

Вот способ сделать это: мы вычисляем отдельно позиции букв и разделителей для ясности и используем scale_x_continuous / breaks / labels для их построения.

l <- rle(df$name)$lengths
letter_pos <- cumsum(c(0,head(l,-1))) + l/2 + .5
sep_pos <- cumsum(l) + .5

ggplot(df, aes(x=id,y=count)) + geom_bar(stat="identity") +
  scale_x_continuous(breaks = c(letter_pos, sep_pos),
                     labels = c(unique(df$name),rep("|",length(letter_pos))))

1
Moody_Mudskipper 18 Сен 2018 в 00:38