#r #dataframe
Вопрос:
В R у меня есть фрейм данных, подобный этому:
df1 lt;- data.frame( grade = rep(LETTERS[1:5], 4), sex = c(rep("male", 5), rep("female", 5), rep("male", 4), rep("female", 6)), class = c(rep(1, 10), rep(2, 10)) ) df1 grade sex class 1 A male 1 2 B male 1 3 C male 1 4 D male 1 5 E male 1 6 A female 1 7 B female 1 8 C female 1 9 D female 1 10 E female 1 11 A male 2 12 B male 2 13 C male 2 14 D male 2 15 E female 2 16 A female 2 17 B female 2 18 C female 2 19 D female 2 20 E female 2
Я хочу подсчитать процент секса в каждом классе и сделать еще один кадр данных.:
Class Male_percent Female_percentage 1 50% 50% 2 40% 60%
Может ли кто-нибудь научить меня, как это сделать? Этот вопрос, возможно, задавали раньше, но я не знаю, какое ключевое слово для этого вопроса. Мне жаль, если я снова задам тот же вопрос.
Ответ №1:
Вы можете попробовать
prop.table(table(df1[3:2]),1)*100 # sex #class female male # 1 50 50 # 2 60 40
Или с data.table
library(data.table) setDT(df1)[, .N, by = .(class, sex) ][, .(Male_percent = paste0(100 * N[sex == 'male'] / sum(N), '%'), Female_percent = paste0(100 * N[sex == 'female'] / sum(N), '%')), by = class] # class Male_percent Female_percent #1: 1 50% 50% #2: 2 40% 60%
Или с помощью dplyr
library(dplyr) df1 %gt;% group_by(class) %gt;% summarise(Male_Percent= sprintf('%d%%', 100*sum(sex=='male')/n()), Female_Percent = sprintf('%d%%', 100*sum(sex=='female')/n())) # class Male_Percent Female_Percent #1 1 50% 50% #2 2 40% 60%
Или
library(sqldf) res1 lt;- sqldf('select class, 100*sum(sex=="male")/count(sex) as m, 100*sum(sex=="female")/count(sex) as f, "%" as p from df1 group by class') sqldf("select class, m||p as Male_Percent, f||p as Female_Percent from res1") # class Male_Percent Female_Percent #1 1 50% 50% #2 2 40% 60%
Обновить
На основе @G.Комментарии Гротендика, sqldf
комментарии могут быть упрощены до
sqldf("select class, (100 * avg(sex = 'male')) || '%' as Male_Percent, (100 * avg(sex = 'female')) || '%' as Female_Percent from df1 group by class") # class Male_Percent Female_Percent #1 1 50.0% 50.0% #2 2 40.0% 60.0%
Комментарии:
1. @G. Гротендик Спасибо, что так намного лучше.
Ответ №2:
Попробуйте tabyl
из пакета уборщика:
library(janitor) df1 %gt;% tabyl(class, sex) %gt;% adorn_percentages() class female male 1 0.5 0.5 2 0.6 0.4
Если вы хотите отформатировать в процентах, добавьте adorn_pct_formatting()
:
df1 %gt;% tabyl(class, sex) %gt;% adorn_percentages() %gt;% adorn_pct_formatting() class female male 1 50.0% 50.0% 2 60.0% 40.0%
Отказ от ответственности: Я являюсь автором этих функций.
Ответ №3:
используя data.table
пакет, вы можете сделать следующее
setDT(df)[ , .( Male_Percent = paste0(( nrow(.SD[sex == "male"]) / .N ) * 100 , "%") , Female_Percent = paste0(( nrow(.SD[sex == "female"]) / .N ) * 100 , "%") ) , by = class ]
Результат
# class Male_Percent Female_Percent # 1: 1 50% 50% # 2: 2 40% 60%
другим dplyr
решением будет
df %gt;% group_by(sex , class) %gt;% summarise(n = n()) %gt;% group_by(class) %gt;% summarise( Male_Percent = paste0((n[sex == "male"] / sum(n)) * 100 , "%") , Female_Percent = paste0((n[sex == "female"] / sum(n) * 100) , "%") ) # class Male_Percent Female_Percent # 1 50% 50% # 2 40% 60%
Комментарии:
1. Я думаю, вы намеревались прокомментировать другой ответ 🙂