私は、棒グラフのカテゴリを(再)並べ替える方法について、多くの質問(しばしば 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
私たちが得るものは次のとおりです:
私が欲しいのは:
それでは、哲学を除いて、そして誰かが興味を持っている場合は、ここにそれを行うための醜いハックがあります。アイデアは、異なるラベルを使用することです(ピリオドを0スペース、1スペースなどに置き換えて表示されないようにする以外は、paste(period, name)
と考えてください)。共通の伝説などを共有したいので、このプロットが必要です。グロブなどを配置したくありません。
前述のアトミックな例は次のようになります。
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
_ packageを使用しますが、この目的のために任意のパッケージを自由に使用できます。
_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))
_
OPの目標を達成するには、いくつかの異なる方法があります この答え
(1) reorder_within()
name
ファセット内でperiod
を並べ替える関数。
library(tidyverse)
library(forcats)
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)
)
reorder_within <- function(x, by, within, fun = mean, sep = "___", ...) {
new_x <- paste(x, within, sep = sep)
stats::reorder(new_x, by, FUN = fun)
}
scale_x_reordered <- function(..., sep = "___") {
reg <- paste0(sep, ".+$")
ggplot2::scale_x_discrete(labels = function(x) gsub(reg, "", x), ...)
}
ggplot(df, aes(reorder_within(name, val, period), val)) +
geom_col() +
scale_x_reordered() +
facet_grid(period ~ ., scales = "free", space = "free") +
coord_flip() +
theme_minimal() +
theme(panel.grid.major.y = element_blank())
または(2)同様のアイデア
### https://trinkerrstuff.wordpress.com/2016/12/23/ordering-categories-within-ggplot2-facets/
df %>%
mutate(name = reorder(name, val)) %>%
group_by(period, name) %>%
arrange(desc(val)) %>%
ungroup() %>%
mutate(name = factor(paste(name, period, sep = "__"),
levels = rev(paste(name, period, sep = "__")))) %>%
ggplot(aes(name, val)) +
geom_col() +
facet_grid(period ~., scales = "free", space = 'free') +
scale_x_discrete(labels = function(x) gsub("__.+$", "", x)) +
coord_flip() +
theme_minimal() +
theme(panel.grid.major.y = element_blank()) +
theme(axis.ticks.y = element_blank())
または(3)データフレーム全体を並べ替え、各ファセットグループ内のカテゴリ(period
)も並べ替えます。
### https://drsimonj.svbtle.com/ordering-categories-within-ggplot2-facets
#
df2 <- df %>%
# 1. Remove any grouping
ungroup() %>%
# 2. Arrange by
# i. facet group (period)
# ii. value (val)
arrange(period, val) %>%
# 3. Add order column of row numbers
mutate(order = row_number())
df2
#> name period val order
#> 1 foo old 1.23 1
#> 2 bar old 2.17 2
#> 3 bar recent 3.65 3
#> 4 foo recent 4.15 4
ggplot(df2, aes(order, val)) +
geom_col() +
facet_grid(period ~ ., scales = "free", space = "free") +
coord_flip() +
theme_minimal() +
theme(panel.grid.major.y = element_blank())
# To finish we need to replace the numeric values on each x-axis
# with the appropriate labels
ggplot(df2, aes(order, val)) +
geom_col() +
scale_x_continuous(
breaks = df2$order,
labels = df2$name) +
# scale_y_continuous(expand = c(0, 0)) +
facet_grid(period ~ ., scales = "free", space = "free") +
coord_flip() +
theme_minimal() +
theme(panel.grid.major.y = element_blank()) +
theme(legend.position = "bottom",
axis.ticks.y = element_blank())
2018-11-05に reprexパッケージ (v0.2.1.9000)によって作成されました
これを試してください、それは本当に簡単です(警告を無視してください)
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