Как подсчитать и рассчитать проценты для двух столбцов в R-кадре данных?

#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. Я думаю, вы намеревались прокомментировать другой ответ 🙂