Распределите долю одной категории категориальной переменной относительно всех категорий второй переменной - PullRequest
1 голос
/ 10 февраля 2020

У меня есть такой фрейм данных:

df <- data.frame(Reason = sample(rep(c("R1", "R2", "R3", "R4"), each = 100)),
                 Answer = sample(rep(c("yes", "no", "no", "no"), 100)))

head(df)

Я хочу, чтобы ggplot сделал гистограмму, показывающую долю ответов "да" (ось Y) для каждой причины (ось X) .

Я пробовал это:

ggplot(data = df, aes(x = interaction(Reason, Answer))) + 
 geom_bar(aes(y = ..count../sum(..count..)))

Это приводит к следующему результату:

как это выглядит

Проблема в том, что сумма баров до 1 (всего). Я хочу, чтобы они суммировали по одному в каждой категории разума. (R1.no и R1.yes должны иметь сумму до 1, R2.no и R2.yes должны иметь сумму до одного и т. Д.).

Когда это будет сделано, я хочу отбросить все столбцы, содержащие информацию про "нет" - ответы. В общем, я просто хочу получить ответы «да» в каждой категории разума. Это должно выглядеть примерно так:

как это должно выглядеть

Я получил желаемый результат следующим образом:

a <- prop.table(table(df$Reason, df$Answer),1)

df2 <- data.frame(Reason = rownames(as.matrix(a)),
                  share = as.matrix(a)[,2])

ggplot(data = df2, aes(x = reorder(Reason, share), y = share)) + 
  geom_bar(stat = "identity") + 
  ylab("share of yes-answers")

Можно ли избежать это обходной путь и напрямую получить желаемый результат от ggplot? Это будет иметь для меня некоторые важные преимущества.

Большое спасибо, Анди

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Решение Юрия работает только тогда, когда оно суммирует до 100. Я думаю, что вы должны как-то рассчитать пропорцию, иначе вы не сможете отсортировать заранее. Итак, в первой части я манипулирую данными, добавляя столбец p, 1, если да, 0, если нет.

library(dplyr)
library(ggplot2)
set.seed(99)
df <- data.frame(
Reason = sample(rep(c("R1", "R2", "R3", "R4"), each = 100)),
Answer = sample(rep(c("yes", "no", "no", "no"), 100)))

head(df %>% mutate(p=as.numeric(Answer=="yes")),3)
  Reason Answer p
1     R3     no 0
2     R3    yes 1
3     R1     no 0

Затем мы строим график с этим фреймом данных, а ось y является просто средним значением каждого группа на оси х, и мы можем использовать stat_summary с fun.y=mean. Теперь reorder работает очень хорошо в этом случае, потому что вычисляет средние значения для каждой категории и переупорядочивает в соответствии с этим:

ggplot(df %>% mutate(p=as.numeric(Answer=="yes")),
aes(x=reorder(Reason,p),y=p)) +
 stat_summary(fun.y="mean",geom="bar",fill="orchid4")

enter image description here

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

set.seed(100)
df <- data.frame(
Reason = rep(c("R1", "R2", "R3", "R4"),times=seq(50,200,length.out=4)),
Answer = sample(c("yes","no"),500,prob=c(0.5,0.5),replace=TRUE)
)
# we expect
sort(tapply(df$Answer=="yes",df$Reason,mean))
R2    R4    R3    R1 
0.460 0.505 0.520 0.540 

ggplot(df %>% mutate(p=as.numeric(Answer=="yes")),
    aes(x=reorder(Reason,p),y=p)) +
     stat_summary(fun.y="mean",geom="bar",fill="orange")

enter image description here

0 голосов
/ 10 февраля 2020
ggplot(df[df$Answer == "yes", ]) + 
  geom_bar(aes(x = Reason, y = sort(..prop..), group = 1))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...