группировать по и условно суммировать в R

#r #dplyr

#r #dplyr

Вопрос:

Мой код грязный. если условие меньше двух, имена = непопулярны.

 df <- data.frame(vote=c("A","A","A","B","B","B","B","B","B","C","D"),
           val=c(rep(1,11))
           )

df %>% group_by(vote) %>% summarise(val=sum(val))
  
 out

  vote    val
  <fct> <dbl>
1 A         3
2 B         6
3 C         1
4 D         1

  

но мне нужно

   vote    val
  <fct> <dbl>
1 A         3
2 B         6
3 unpopular 2

  

моя идея такова

 df2 <- df %>% group_by(vote) %>% summarise(val=sum(val))
df2$vote[df2$val < 2] <- "unpop"
df2 %>% group_by....
  

это не круто.

знаете ли вы какую-нибудь классную и полезную функцию?

Ответ №1:

Мы можем выполнить двойную группировку

 library(dplyr)
df %>% 
    group_by(vote) %>% 
    summarise(val=sum(val)) %>%
    group_by(vote = replace(vote, val <2, 'unpop')) %>% 
    summarise(val = sum(val))
  

-вывод

 # A tibble: 3 x 2
# vote    val
#  <chr> <dbl>
#1 A         3
#2 B         6
#3 unpop     2
  

Или другой вариант с rowsum

 df %>% 
   group_by(vote = replace(vote, vote %in% 
     names(which((rowsum(val, vote) < 2)[,1])), 'unpopular')) %>% 
   summarise(val = sum(val))
  

Или использовать fct_lump_n из forcats

 library(forcats)
df %>% 
  group_by(vote = fct_lump_n(vote, 2, other_level = "unpop")) %>%
  summarise(val = sum(val))
# A tibble: 3 x 2
#  vote    val
#  <fct> <dbl>
#1 A         3
#2 B         6
#3 unpop     2
  

Или с помощью table

 df %>%
   group_by(vote = replace(vote, 
      vote %in% names(which(table(vote) < 2)), 'unpop'))  %>%
   summarise(val = sum(val))
  

Ответ №2:

Если вы хотите на vote основе sum of val в базе R, вы можете сделать это следующим образом :

 aggregate(val~vote, transform(aggregate(val~vote, df, sum), 
          vote = replace(vote, val < 2, 'unpop')), sum)

#   vote val
#1     A   3
#2     B   6
#3 unpop   2