гистограмма ggplot с фасеточно-зависимым порядком категорий


Я видел много вопросов (часто связанных с упорядочиванием баров в гистограмме ggplot2) о том, как (повторно)упорядочивать категории в гистограмме.

То, что я ищу, просто немного отличается, но я не нашел хорошего способа сделать это: у меня есть многогранная линейчатая диаграмма, и я хочу упорядочить ось x для каждой грани независимо, в соответствии с другой переменной (в моем случае эта переменная является просто значением y, т. е. я просто хочу, чтобы бары шли в возрастающей длине в каждом направлении). грань).

Простой пример, следующий, например, Порядок баров в гистограмме ggplot2 :

df <- data.frame(name=c('foo','bar','foo','bar'),period=c('old','old','recent','recent'),val=c(1.23,2.17,4.15,3.65))
p = ggplot(data = df, aes(x = reorder(name, val), y = val))
p = p + geom_bar(stat='identity')
p = p + facet_grid(~period)
p

Мы получаем следующее:: Введите описание изображения здесь

В то время как то, что я хочу, это: Введите описание изображения здесь

3   12  

3 ответа:

Ладно, Так что все философствование в сторону, и в случае, если кто-то заинтересован, вот уродливый хак, чтобы сделать это. Идея состоит в том, чтобы использовать разные метки (подумайте paste(period, name), Кроме того, что я заменяю точку на 0-пробел, 1-пробел и т. д. чтобы они не показывались). Мне нужен этот сюжет, и я не хочу устраивать гробов и тому подобное, потому что я могу захотеть поделиться общей легендой и т. д.

Атомарный пример, приведенный ранее, становится:

df <- data.frame(name=c('foo','bar','foo','bar'),
  period=c('old','old','recent','recent'),
  val=c(1.23,2.17,4.15,3.65),
  stringsAsFactors=F)
df$n = as.numeric(factor(df$period))
df = ddply(df,.(period,name),transform, x=paste(c(rep(' ',n-1), name), collapse=''))
df$x = factor(df$x, levels=df[order(df$val), 'x'])
p = ggplot(data = df, aes(x = x, y = val))
p = p + geom_bar(stat='identity')
p = p + facet_grid(~period, scale='free_x')
p

Введите описание изображения здесьДругой пример, все еще немного глупый, но ближе к моему фактическому использованию случай, было бы:

df <- ddply(mpg, .(year, manufacturer), summarize, mixmpg = mean(cty+hwy))
df$manufacturer = as.character(df$manufacturer)
df$n = as.numeric(factor(df$year))
df = ddply(df, .(year,manufacturer), transform,
     x=paste(c(rep(' ',n-1), manufacturer), collapse=''))
df$x = factor(df$x, levels=df[order(df$mixmpg), 'x'])
p = ggplot(data = df, aes(x = x, y = mixmpg))
p = p + geom_bar(stat='identity')
p = p + facet_grid(~year, scale='free_x')
p = p + theme(axis.text.x=element_text(angle=90,hjust=1,vjust=.5,colour='gray50'))
p

Введите описание изображения здесьЗакройте глаза, думайте об Империи и постарайтесь наслаждаться.

Это старый вопрос,но он используется в качестве мишени для обмана. Поэтому, возможно, стоит предложить решение, которое использует последние усовершенствования пакета ggplot2, а именно параметр labels для scale_x_discrete(). Это позволяет избежать использования повторяющихся уровней , которые являются устаревшими, или манипулирования метками факторов, предваряя различное число пробелов.

Подготовка данных

Здесь набор данных mpg используется для сравнения сэтим ответом . Для данных манипуляция, пакет data.tableиспользуется здесь, но не стесняйтесь использовать любой пакет, который вы предпочитаете для этой цели.

library(data.table)   # version 1.10.4
library(ggplot2)      # version 2.2.1
# aggregate data
df <- as.data.table(mpg)[, .(mixmpg = mean(cty + hwy)), by = .(year, manufacturer)]
# create dummy var which reflects order when sorted alphabetically
df[, ord := sprintf("%02i", frank(df, mixmpg, ties.method = "first"))]

Создать сюжет

# `ord` is plotted on x-axis instead of `manufacturer`
ggplot(df, aes(x = ord, y = mixmpg)) +
  # geom_col() is replacement for geom_bar(stat = "identity")
  geom_col() +
  # independent x-axis scale in each facet, 
  # drop absent factor levels (actually not required here)
  facet_wrap(~ year, scales = "free_x", drop = TRUE) +
  # use named character vector to replace x-axis labels
  scale_x_discrete(labels = df[, setNames(as.character(manufacturer), ord)]) + 
  # replace x-axis title
  xlab(NULL) +
  # rotate x-axis labels
  theme(axis.text.x = element_text(angle = 90, hjust=1, vjust=.5))

Введите описание изображения здесь

Попробуйте это, это действительно просто (просто игнорировать предупреждения)

df <-data.frame(name = c('foo', 'bar', 'foo', 'bar'),
                period = c('old', 'old', 'recent', 'recent'),
                val = c(1.23, 2.17, 4.15, 3.65))

d1 <- df[order(df$period, df$val), ]
sn <- factor(x = 1:4, labels = d1$name)
d1$sn <- sn
p <- ggplot(data = d1, aes(x = sn, y = val))
p <- p + geom_bar(stat = 'identity')
p <- p + facet_wrap(~ period, scale = 'free_x')
p