Показывать% вместо количества в диаграммах категориальных переменных
Я строю категориальную переменную и вместо того, чтобы показывать счетчики для каждого значения категории.
Я ищу способ получить 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
взаимодействует с одним вектором. Я чешу голову, гуглюсь из-за этой ошибки, даю единственный результат.
10 ответов
После того, как на этот вопрос был дан ответ, в 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
Этот вопрос в настоящее время является хитом № 1 в Google по показателю "ggplot count vs процент гистограммы", так что, надеюсь, это поможет найти всю информацию, размещенную в комментариях к принятому ответу.
Примечание: если hp
не устанавливается как фактор, ggplot возвращает:
Этот модифицированный код должен работать
p = ggplot(mydataf, aes(x = foo)) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent')
если у ваших данных есть NA, и вы не хотите, чтобы они были включены в график, передайте g.gplot аргумент na.omit(mydataf) в качестве аргумента.
надеюсь это поможет.
С ggplot2 версии 2.1.0 это
+ scale_y_continuous(labels = scales::percent)
По состоянию на март 2017 года, с ggplot2
2.2.1 Я думаю, что лучшее решение объясняется в книге Хэдли Уикхэма для книги по науке о данных:
ggplot(mydataf) + stat_count(mapping = aes(x=foo, y=..prop.., group=1))
stat_count
вычисляет две переменные: count
используется по умолчанию, но вы можете использовать prop
который показывает пропорции.
Если вы хотите, чтобы проценты по оси 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()
)
Начиная с версии 3.3 ggplot2 , у нас есть доступ к удобному
after_stat()
функция.
Мы можем сделать что-то похожее на ответ @ Andrew, но без использования
..
синтаксис:
# original example data
mydata <- c("aa", "bb", NULL, "bb", "cc", "aa", "aa", "aa", "ee", NULL, "cc")
# display percentages
library(ggplot2)
ggplot(mapping = aes(x = mydata,
y = after_stat(count/sum(count)))) +
geom_bar() +
scale_y_continuous(labels = scales::percent)
Вы можете найти все "вычисляемые переменные", доступные для использования, в документации к
geom_
и
stat_
функции. Например, для
geom_bar()
, вы можете получить доступ к
count
и
prop
переменные. (См. Документацию по вычисляемым переменным .)
Один комментарий о вашем
NULL
значения: они игнорируются при создании вектора (т. е. вы получаете вектор длиной 9, а не 11). Если вы действительно хотите отслеживать недостающие данные, вам придется использовать
NA
вместо этого (ggplot2 поместит NA в правый конец графика):
# use NA instead of NULL
mydata <- c("aa", "bb", NA, "bb", "cc", "aa", "aa", "aa", "ee", NA, "cc")
length(mydata)
#> [1] 11
# display percentages
library(ggplot2)
ggplot(mapping = aes(x = mydata,
y = after_stat(count/sum(count)))) +
geom_bar() +
scale_y_continuous(labels = scales::percent)
Создано 2021-02-09 пакетом REPEX (v1.0.0)
(Обратите внимание, что использование
chr
или же
fct
данные не будут иметь значения для вашего примера.)
Обратите внимание, что если ваша переменная является непрерывной, вам придется использовать 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..)))
Вот обходной путь для граненых данных. (Принятый ответ @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~.)
Это сюжет:
Если вам нужны процентные метки, но фактические значения N на оси 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)
Для тех, кто придет к этому после 2018 года, замените "метки = процент_формат ()" на "масштаб:: проценты"