Показывать% вместо графов в диаграммах категориальных переменных
Я строю категориальную переменную и вместо того, чтобы показывать счетчики для каждого значения категории.
Я ищу способ получить ggplot
для отображения процента значений в этой категории. Конечно, можно создать другую переменную с вычисленным процентом и построить ее, но я должен сделать это несколько десятков раз, и я надеюсь добиться этого одной командой.
Я экспериментировал с чем-то вроде
qplot(mydataf) +
stat_bin(aes(n = nrow(mydataf), y = ..count../n)) +
scale_y_continuous(formatter = "percent")
но я должен использовать его неправильно, так как я получил ошибки.
Чтобы легко воспроизвести настройку, вот упрощенный пример:
mydata <- c ("aa", "bb", NULL, "bb", "cc", "aa", "aa", "aa", "ee", NULL, "cc");
mydataf <- factor(mydata);
qplot (mydataf); #this shows the count, I'm looking to see % displayed.
В реальном случае я, вероятно, буду использовать ggplot
вместо qplot
, но правильный путь использования stat_bin все же ускользает от меня.
Я также попробовал эти четыре подхода:
ggplot(mydataf, aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent');
ggplot(mydataf, aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent') + geom_bar();
ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent');
ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent') + geom_bar();
но все 4 дают:
Error: ggplot2 doesn't know how to deal with data of class factor
Та же ошибка появляется для простого случая
ggplot (data=mydataf, aes(levels(mydataf))) +
geom_bar()
так что ясно, что ggplot
взаимодействует с одним вектором. Я чешу голову, гуглюсь из-за этой ошибки, даю единственный результат.
Ответы
Ответ 1
С тех пор как на этот вопрос был дан ggplot
синтаксисе ggplot
произошли существенные изменения. Подводя итоги обсуждения в комментариях выше:
require(ggplot2)
require(scales)
p <- ggplot(mydataf, aes(x = foo)) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
## version 3.0.0
scale_y_continuous(labels=percent)
Вот воспроизводимый пример с использованием mtcars
:
ggplot(mtcars, aes(x = factor(hp))) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(labels = percent) ## version 3.0.0
![enter image description here]()
Этот вопрос в настоящее время является хитом № 1 в Google по показателю "ggplot count vs процент гистограммы", поэтому, надеюсь, это поможет отыскать всю информацию, размещенную в настоящее время в комментариях к принятому ответу.
Примечание: если hp
не установлен как фактор, ggplot возвращает:
![enter image description here]()
Ответ 2
этот модифицированный код должен работать
p = ggplot(mydataf, aes(x = foo)) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent')
если ваши данные имеют NA, и вы не хотите, чтобы они были включены в график, передайте na.omit(mydataf) в качестве аргумента ggplot.
надеюсь, что это поможет.
Ответ 3
С ggplot2 версии 2.1.0 это
+ scale_y_continuous(labels = scales::percent)
Ответ 4
По состоянию на март 2017 года, с ggplot2
2.2.1, я думаю, что лучшее решение объясняется в Hadley Wickham R для книги по науке о данных:
ggplot(mydataf) + stat_count(mapping = aes(x=foo, y=..prop.., group=1))
stat_count
вычисляет две переменные: по умолчанию используется count
, но вы можете использовать prop
, который показывает пропорции.
Ответ 5
Если вы хотите проценты по оси Y и помечены на барах:
library(ggplot2)
library(scales)
ggplot(mtcars, aes(x = as.factor(am))) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))), stat = "count", vjust = -0.25) +
scale_y_continuous(labels = percent) +
labs(title = "Manual vs. Automatic Frequency", y = "Percent", x = "Automatic Transmission")
![введите описание изображения здесь]()
При добавлении ярлыков на панели вы можете опустить ось y для более чистой диаграммы, добавив в конец:
theme(
axis.text.y=element_blank(), axis.ticks=element_blank(),
axis.title.y=element_blank()
)
![введите описание изображения здесь]()
Ответ 6
Если вам нужны процентные метки, но фактические Ns на оси y, попробуйте следующее:
library(scales)
perbar=function(xx){
q=ggplot(data=data.frame(xx),aes(x=xx))+
geom_bar(aes(y = (..count..)),fill="orange")
q=q+ geom_text(aes(y = (..count..),label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="darkgreen")
q
}
perbar(mtcars$disp)
Ответ 7
Вот обходной путь для граненых данных. (Принятый ответ @Andrew в этом случае не работает.) Идея состоит в том, чтобы рассчитать процентное значение с помощью dplyr, а затем использовать geom_col для создания графика.
library(ggplot2)
library(scales)
library(magrittr)
library(dplyr)
binwidth <- 30
mtcars.stats <- mtcars %>%
group_by(cyl) %>%
mutate(bin = cut(hp, breaks=seq(0,400, binwidth),
labels= seq(0+binwidth,400, binwidth)-(binwidth/2)),
n = n()) %>%
group_by(cyl, bin) %>%
summarise(p = n()/n[1]) %>%
ungroup() %>%
mutate(bin = as.numeric(as.character(bin)))
ggplot(mtcars.stats, aes(x = bin, y= p)) +
geom_col() +
scale_y_continuous(labels = percent) +
facet_grid(cyl~.)
Это сюжет:
![enter image description here]()
Ответ 8
Для тех, кто придет к этому после 2018 года, замените "метки = процент_формат()" на "метки = весы :: проценты"
Ответ 9
Обратите внимание, что если ваша переменная является непрерывной, вам придется использовать geom_histogram(), так как функция сгруппирует переменную по "bin".
df <- data.frame(V1 = rnorm(100))
ggplot(df, aes(x = V1)) +
geom_histogram(aes(y = (..count..)/sum(..count..)))
# if you use geom_bar(), with factor(V1), each value of V1 will be treated as a
# different category. In this case this does not make sense, as the variable is
# really continuous. With the hp variable of the mtcars (see previous answer), it
# worked well since hp was not really continuous (check unique(mtcars$hp)), and one
# can want to see each value of this variable, and not to group it in bins.
ggplot(df, aes(x = factor(V1))) +
geom_bar(aes(y = (..count..)/sum(..count..)))