R dplyr вычисляет процентное соотношение групп и столбцов

#r #dplyr

#r #dplyr

Вопрос:

Я новичок в R, и у меня есть простой вопрос «как это сделать», в частности, каков наилучший способ вычисления групповых и общих процентов по столбцам фрейма данных? Мои данные выглядят так:

 # A tibble: 13 x 3
   group  resp id   
   <chr> <dbl> <chr>
 1 A         1 ssa  
 2 A         1 das  
 3 A        NA fdsf 
 4 B        NA gfd  
 5 B         1 dfg  
 6 B         1 dg   
 7 C         1 gdf  
 8 C        NA gdf  
 9 C        NA hfg  
10 D         1 hfg  
11 D         1 trw  
12 D         1 jyt  
13 D        NA ghj
 

тестовые данные таковы:

 structure(list(group = c("A", "A", "A", "B", "B", "B", "C", "C", 
"C", "D", "D", "D", "D"), resp = c(1, 1, NA, NA, 1, 1, 1, NA, 
NA, 1, 1, 1, NA), id = c("ssa", "das", "fdsf", "gfd", "dfg", 
"dg", "gdf", "gdf", "hfg", "hfg", "trw", "jyt", "ghj")), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame")
 

Мне удалось вычислить групповые проценты, выполнив следующее (что кажется чрезмерно сложным)::

 a <- test %>% 
  group_by(group) %>% 
  summarise(no_resp = sum(resp, na.rm = TRUE))

b <- test %>%  
  group_by(group) %>% 
  summarise(all = n_distinct(id, na.rm = TRUE))

result <- a %>% 
  left_join(b) %>% 
  mutate(a,resp_rate = round(no_resp/all*100))
 

это дает мне:

 # A tibble: 4 x 4
  group no_resp   all resp_rate
  <chr>   <dbl> <int>     <dbl>
1 A           2     3        67
2 B           2     3        67
3 C           1     2        50
4 D           3     4        75
 

и это прекрасно, но я задавался вопросом, как я мог бы сделать это проще? Кроме того, как бы я сделал общий процент? Например. общее отдельное количество соответственно / отдельное количество идентификаторов, без группировки.

Большое спасибо

Ответ №1:

Вы можете добавить несколько операторов, summarise чтобы вам не приходилось создавать временные объекты a и b . Чтобы рассчитать общий процент, вы можете разделить это число на сумму столбца.

 library(dplyr)

test %>%
  group_by(group) %>%
  summarise(no_resp = sum(resp, na.rm = TRUE), 
            all = n_distinct(id), 
            resp_rate = round(no_resp/all*100)) %>%
  mutate(no_resp_perc = no_resp/sum(no_resp) * 100)

#  group no_resp   all resp_rate no_resp_perc
#  <chr>   <int> <int>     <dbl>        <dbl>
#1 A           2     3        67         25  
#2 B           2     3        67         25  
#3 C           1     2        50         12.5
#4 D           3     4        75         37.5
 

Ответ №2:

Используя базу R, мы можем применять tapply table функции и .

 res <- transform(with(test, data.frame(no_resp=tapply(resp, group, sum, na.rm=TRUE),
                                       all=colSums(table(id, group) > 0))), 
                 resp_rate=round(no_resp/all*100),
                 overall_perc=prop.table(no_resp)*100
                 )
res
#   no_resp all resp_rate overall_perc
# A       2   3        67         25.0
# B       2   3        67         25.0
# C       1   2        50         12.5
# D       3   4        75         37.5