Сгруппированные полосы частот в R с использованием ggplot

Я пытаюсь создать гистограмму с частотами нескольких групп. Я пытался использовать geom_bar(), но постоянно сталкивался с ошибкой: stat_count() нельзя использовать с эстетикой y. У меня есть одна строка для каждого участника с возрастом (2 категории), состоянием (2 категории) и их производительностью (0 или 1). Из того, что я прочитал в руководстве и практически везде в Интернете, если я использую

bar<-ggplot(data, aes(age, performance, fill = condition)) + geom_bar(position = "dodge")

Я должен получить то, что хочу (а именно это), но вместо этого получаю сообщение об ошибке и я не могу понять, что мне не хватает. Разве geom_bar() не должен давать счетчик по умолчанию? Когда я использую stat="identity", я получаю полные полосы, например: как это выглядит на самом деле. Пожалуйста помоги! Любой совет будет принят с благодарностью.

EDITED: Вот мои фактические данные:

structure(list(ageyears = c(4L, 4L, 5L, 5L, 5L, 4L, 5L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 
4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 4L, 4L, 4L, 4L, 5L, 4L, 
5L, 5L, 4L, 4L, 4L, 5L, 4L, 4L, 5L, 4L, 5L, 4L, 4L, 5L, 5L, 4L, 
4L, 5L, 4L, 5L, 4L, 5L, 4L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 5L, 4L, 4L, 5L, 5L, 4L, 5L, 5L, 4L, 4L, 
5L, 5L, 5L, 4L, 5L, 5L, 4L, 5L, 5L, 4L, 4L, 5L, 4L, 5L, 5L, 4L, 
5L, 4L, 4L, 5L, 5L, 4L, 5L, 5L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 
5L, 5L, 5L, 4L, 5L, 5L, 4L, 5L, 5L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 
4L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 5L, 5L, 5L, 
5L, 5L, 4L, 4L, 4L, 5L, 4L), MatrixLabels = structure(c(2L, 2L, 
1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 
1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 
1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
2L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 
1L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 
2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("0", 
"1"), class = "factor"), Mat_sort_pass_fail = c(0L, 0L, 1L, 1L, 
0L, 0L, 1L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 
1L, 1L, 1L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 
0L, 0L, 0L, 1L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 
1L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 
1L, 1L, 0L, 0L, 0L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L, 
0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 0L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 
1L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 1L, 0L, 1L, 0L)), .Names = c("ageyears", 
"MatrixLabels", "Mat_sort_pass_fail"), row.names = c(1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 11L, 12L, 13L, 15L, 16L, 17L, 18L, 19L, 
20L, 21L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L, 
34L, 35L, 36L, 37L, 38L, 40L, 41L, 42L, 43L, 44L, 45L, 46L, 48L, 
49L, 50L, 51L, 52L, 53L, 54L, 55L, 56L, 57L, 58L, 60L, 61L, 62L, 
63L, 64L, 65L, 66L, 67L, 68L, 69L, 70L, 71L, 72L, 74L, 75L, 76L, 
77L, 78L, 79L, 80L, 82L, 83L, 85L, 86L, 87L, 88L, 89L, 90L, 91L, 
92L, 93L, 94L, 95L, 96L, 97L, 98L, 99L, 100L, 101L, 102L, 103L, 
104L, 105L, 106L, 107L, 108L, 109L, 110L, 111L, 112L, 113L, 114L, 
115L, 116L, 117L, 118L, 119L, 120L, 121L, 122L, 123L, 124L, 125L, 
126L, 127L, 128L, 129L, 130L, 131L, 132L, 133L, 134L, 135L, 136L, 
137L, 138L, 139L, 140L, 141L, 142L, 143L, 144L, 145L, 146L, 147L, 
148L, 149L, 150L, 151L, 152L, 153L, 154L, 155L, 156L, 157L, 158L, 
159L, 160L, 197L, 198L, 200L, 201L, 202L, 203L, 204L, 205L, 206L, 
207L), class = "data.frame")

person Gal Podjarny    schedule 28.04.2017    source источник


Ответы (3)


Из документации geom_bar :

По умолчанию geom_bar использует stat="count", что делает высоту столбца пропорциональной количеству случаев в каждой группе (или, если указан весовой коэффициент, сумме весов). Если вы хотите, чтобы высота столбцов представляла значения в данных, используйте stat="identity" и сопоставьте переменную с эстетикой y.

В вашем случае вы должны использовать высоту как сумму своей производительности, поскольку у вас есть сводные данные, поэтому ggplot должен использовать stat = identity

EDIT После того, как OP вставил вывод:

Сначала вам нужно обобщить ваши данные, я предполагаю, что df — это ваш фрейм данных, вы можете использовать что угодно для суммирования, я использую агрегат data.table и baseR, вы можете выбрать любой из них, чтобы сделать это, как показано ниже:

###1. base R aggregate

 df <- aggregate(Mat_sort_pass_fail ~ ageyears + MatrixLabels, data=df1 ,sum)
df$perc <- df$Mat_sort_pass_fail/sum(df$Mat_sort_pass_fail)
names(df) <- c("age","condition","performance","percentage")



###2. sumarization using data.table
library(data.table)

dt <- setDT(df)
dt1 <- dt[,list(Performance = sum(Mat_sort_pass_fail)),by=c("ageyears","MatrixLabels")]
dt1[,perc:=Performance/sum(Performance)] ##percentage within column

df <- data.frame(dt1)
names(df) <- c("age","condition","performance","percentage")


library(ggplot2)
library(RColorBrewer)

ggplot(df, aes(x = condition ,y=performance)) +
  geom_bar(aes(fill = factor(age)),stat="identity",position = "dodge") +
  ggtitle("Matrix Sort Performance") + 
  scale_fill_brewer(palette = "Dark2")

###In case you need the percentage run the below code:
ggplot(df, aes(x = condition ,y=percentage)) +
  geom_bar(aes(fill = factor(age)),stat="identity",position = "dodge") +
  ggtitle("Matrix Sort Performance") + 
  scale_fill_brewer(palette = "Dark2")

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

person PKumar    schedule 28.04.2017
comment
Спасибо! Итак, когда я использую stat=identity, я получаю странный график (вторая ссылка, которую я прикрепил к исходному вопросу). Что вы имеете в виду, когда говорите, что мои данные суммированы? У меня есть одна строка для каждого участника, я редактирую вопрос, чтобы добавить пример. - person Gal Podjarny; 28.04.2017
comment
@GalPodjarny, вы уверены, что ваша производительность всегда будет 0 и 1, потому что мне кажется, что для получения желаемого графика он должен иметь непрерывную форму, а не дихотомическую форму. Я думаю, что когда вы обобщаете свою таблицу по состоянию и возрасту, ваши показатели должны быть суммированы по их значениям, или это может быть просто подсчет, но это не может быть дихотомическая форма. - person PKumar; 28.04.2017
comment
эта конкретная переменная является переменной «годен/не годен», поэтому она дихотомична. График, который мне нужен, взят из тех же данных, что и в Excel, я просто надеялся воспроизвести его в R, чтобы все графики были сделаны последовательно. Я не суммировал какие-либо данные, я дал ggplot кадр данных, как показано в моем примере. Любая идея, почему ggplot ведет себя так, как он? :) - person Gal Podjarny; 28.04.2017
comment
@GalPodjarny, можете ли вы сделать dput на фрейме данных, dput(df) и вставить его в свой вопрос. - person PKumar; 28.04.2017
comment
@GalPodjarny, я добавил код на случай, если вам нужны проценты, а не суммы. - person PKumar; 28.04.2017
comment
stackoverflow.com/help/someone-answers . @GalPodjarny, отметьте это как ответ. Зеленая галочка - person PKumar; 02.05.2017

Обычно он вычисляет частоты из ваших данных. Если ваши данные уже сгруппированы, попробуйте следующее:

+ geom_bar(stat="identity",position = "dodge")
person Erdem Akkas    schedule 28.04.2017

Вы можете использовать geom_col() как псевдоним для geom_bar(stat = "identity").

У вас также было то, что я считаю неправильным AES Mapping.

Я имитировал некоторые данные на основе графика, который вы опубликовали:

df <- data.frame(age = factor(rep(4:5, each = 2), labels = c('4-Years-Olds', '5-Years-Olds')),
                 performance = c(48,37,65,65),
                 condition = factor(c(1,2,1,2), labels = c('No Label', 'Label')))

library(ggplot2)

ggplot(df) +
    geom_col(aes(condition, performance, fill = age), position = 'dodge') +
    scale_fill_manual(values = c('skyblue', 'darkolivegreen1'))

person GGamba    schedule 28.04.2017
comment
Спасибо! Итак, мне нужно агрегировать данные тогда? Создать таблицу с количеством детей, набравших 1 балл? Потому что это то, что я вижу в вашем коде... Я надеялся, что смогу получить прямой график из вектора? - person Gal Podjarny; 28.04.2017
comment
Работать с не агрегированными данными конечно можно, это я так понял из вашего вопроса. Поделитесь своими данными с «dput(data)», чтобы получить соответствующий ответ - person GGamba; 28.04.2017