#r #ggplot2 #facet-wrap
#r #ggplot2 #обтекание фасета
Вопрос:
Есть ли способ масштабировать ось y при обтекании фасетами от 0 до 1 на основе отображаемой переменной, в моем случае (см. Ниже) пола? Как если бы ..count.. / max(..count..)
данные были сгруппированы по gender
переменной. Любые идеи будут высоко оценены.
Ниже приведена моя текущая попытка
ex[c("var1","var2", "gender")] %>%
gather(-gender, key="var", value = "value") %>%
ggplot(aes(value, fill = gender)) geom_histogram(aes(y=..count.. / max(..count..)), stat="count")
facet_wrap(~var gender, scales = "free_x", ncol= 2)
ylab("% in each group")
Образец данных:
structure(list(row = 1:100, var1 = c(" <25", " <25", " 25-50",
" 25-50", " 50-75", " <25", " 25-50", " 25-50", " 25-50", " 25-50",
" 50-75", " 25-50", " 25-50", " 25-50", " <25", " 25-50", " 25-50",
" 25-50", " 25-50", " 25-50", " 25-50", " 25-50", " 25-50", " 25-50",
">75", " 25-50", " 25-50", " <25", " <25", " 25-50", " 25-50",
" 25-50", " 50-75", " 50-75", " 25-50", " 25-50", " 50-75", " 25-50",
" 25-50", " <25", " 25-50", " 25-50", " 25-50", " 25-50", " <25",
" 25-50", " 25-50", " 25-50", " 25-50", " 25-50", " 25-50", " 25-50",
" 25-50", " 50-75", " 50-75", " <25", " 25-50", " <25", " 50-75",
" <25", " <25", " <25", " 25-50", " <25", " <25", " 25-50", " 50-75",
" 25-50", " 25-50", " 25-50", " 25-50", " 25-50", " <25", " 25-50",
" <25", " 25-50", " 25-50", " 25-50", " 25-50", " 25-50", " <25",
" 50-75", " 25-50", " 25-50", " 25-50", " 25-50", " 25-50", " 50-75",
" 25-50", " <25", " 25-50", " 25-50", " <25", " 25-50", " <25",
" <25", " 25-50", " 25-50", " <25", " <25"), var2 = c(0L, 0L,
0L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L,
0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 1L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
1L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L,
1L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L), gender = c("M", "M", "M", "M", "M", "M", "M", "F", "M",
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M",
"M", "M", "F", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M",
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M",
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M",
"M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M",
"M", "M", "M", "M", "F", "M", "M", "M", "M", "M", "M", "M", "M",
"F", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M"
)), class = "data.frame", row.names = c(NA, -100L))
Комментарии:
1. Не могли бы вы, пожалуйста, уточнить, что должно составлять 100%, может быть, вы сможете дать ожидаемый результат?
Ответ №1:
Насколько мне известно, не существует готового решения, которое указывало бы facet_wrap
выполнять нормализацию, которую вы пытаетесь достичь. Вместо этого вам придется делать это вручную.
Для достижения этого существует (по крайней мере) два подхода:
- Простым подходом было бы предварительное вычисление (нормализованных) значений и использование
geom_col
- Более сложным подходом было бы использовать, например,
tapply
для вычисления максимального количества с помощьюgender
. Для этого подхода я бы рекомендовал переключиться наgeom_bar
вместо использованияgeom_histogram
.
Оба подхода показаны ниже:
library(ggplot2)
library(tidyr)
library(dplyr)
ex[c("var1","var2", "gender")] %>%
gather(-gender, key="var", value = "value") %>%
count(gender, var, value) %>%
group_by(gender) %>%
mutate(pct = n / max(n)) %>%
ggplot(aes(value, pct, fill = gender))
geom_col()
facet_wrap(~var gender, scales = "free_x", ncol= 2)
ylab("% in each group")
ex[c("var1","var2", "gender")] %>%
gather(-gender, key="var", value = "value") %>%
ggplot(aes(value, fill = gender))
geom_bar(aes(y = ..count.. / tapply(..count.., ..fill.., function(x) max(x))[..fill..]), stat="count")
facet_wrap(~var gender, scales = "free_x", ncol= 2)
ylab("% in each group")
Комментарии:
1. Есть ли какой-либо способ, чтобы столбцы внутри каждой категории (для каждой переменной) суммировались до 1? Текущее решение, которое у меня есть, использует
geom_bar(aes(y = ..count.. / tapply(..count.., ..fill.., function(x) sum(x))[..fill..]), stat="count")
для каждой переменной отдельно ylim (0,1), а затем использует grid.arrange, но я считаю, что должно быть более плавное решение? Большое спасибо2. Привет @Randomcloud. Да. grid.arrange не требуется. В целом я бы предположил, что использовать мой первый подход с использованием предварительно вычисленных значений проще в обращении. Там вы можете просто сгруппировать по переменной и полу. Для второго подхода вам нужно сделать
ggplot(aes(value, fill = gender, group = interaction(var, gender))) geom_bar(aes(y = ..count.. / tapply(..count.., ..group.., function(x) sum(x))[..group..]), stat="count")
. Здесь мы сначала сопоставляемinteraction(var, gender)
наgroup
, которые затем могут быть использованы в geom_bar или tapply для выполнения вычислений по переменной / полу …3. … в любом случае вам все равно понадобится ylim (0, 1) для установки ограничений.