гистограмма 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 ответа:
Ладно, Так что все философствование в сторону, и в случае, если кто-то заинтересован, вот уродливый хак, чтобы сделать это. Идея состоит в том, чтобы использовать разные метки (подумайте
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