Как я могу использовать mutate () для создания серии элементов из внешнего списка, которые не отображаются в данном столбце? - PullRequest
2 голосов
/ 16 января 2020

У меня есть данные в виде удостоверения личности и продуктов питания:

adf<-data.frame(ID=c("a","a","a","b","b","b","b","c","c"),
            foods=c("apple","orange","banana","apple","banana","tomato","pear","pear","onion"))

У меня также есть список необходимых продуктов, по которым для каждого удостоверения личности проводится проверка:

required_foods<-c("apple","tomato")

Я заинтересован в создании столбца с именем «missing_foods», в котором содержится разделенный запятыми список всех и всех продуктов в required_foods, которых нет в столбце foods моих данных, сгруппированных по идентификатору.

В desired_output ниже приведен пример того, чего я надеюсь достичь sh.

desired_output<-data.frame(ID=c("a","a","a","b","b","b","b","c","c"),
                       foods=c("apple","orange","banana","apple","banana","tomato","pear","pear","onion"),
                       missing_foods=c("tomato","tomato","tomato","","","","","apple,tomato","apple,tomato"))

Мои попытки решить эту проблему до сих пор были бесплодными. В идеале я надеюсь получить ответ dplyr, который будет иметь гибкость, позволяющую создавать списки required_food различной длины. В конечном итоге я буду составлять несколько необходимых списков _... и надеюсь создать для каждого из них новый столбец.

Мои попытки:

adf2<-adf%>%
  group_by(ID)%>%
 mutate(missing_foods= !(required_foods %in% foods))

adf2<-adf%>%
 group_by(ID)%>%
 mutate(missing_foods= paste(!(required_foods %in% foods),sep=","))

adf2<-adf%>%
  group_by(ID)%>%
  mutate(missing_foods= for (f in 1:length(required_foods)){
                     ifelse(f %in% required_foods,paste0(""),
                            paste0(f,","))
  })

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

3 голосов
/ 16 января 2020

Здесь мы используем desired_output data.frame, так как значения набора данных 'adf' не такие, как в 'required_output'. После группировки по 'ID', получите элементы из 'required_foods', которых нет в 'food', с setdiff, paste их вместе (str_c) и замените любые NA (когда все элементы найдены ) с пустым ("")

library(dplyr)
library(stringr)
library(tidyr)
desired_output %>% 
  group_by(ID) %>% 
  mutate(newmissing_foods = replace_na(str_c(setdiff(required_foods, 
          foods), collapse=", ")[1], ''))
# A tibble: 9 x 4
# Groups:   ID [3]
#  ID    foods  missing_foods  newmissing_foods
#  <fct> <fct>  <fct>          <chr>           
#1 a     apple  "tomato"       "tomato"        
#2 a     orange "tomato"       "tomato"        
#3 a     banana "tomato"       "tomato"        
#4 b     apple  ""             ""              
#5 b     banana ""             ""              
#6 b     tomato ""             ""              
#7 b     pear   ""             ""              
#8 c     pear   "apple,tomato" "apple, tomato" 
#9 c     onion  "apple,tomato" "apple, tomato" 

В коде OP это просто создание логического вектора

!(required_foods %in% foods)

, который должен использоваться для подстановки 'required_foods

desired_output %>% 
   group_by(ID) %>% 
   mutate(newmissing_foods = paste(required_foods[!(required_foods %in% 
             foods)], collapse=", "))

Или с использованием data.table

library(dplyr)
setDT(desired_output)[, newmissing_foods := paste(required_foods[!(required_foods %in% 
             foods)], collapse=", "), ID]

ПРИМЕЧАНИЕ: toString является оберткой для paste(., collapse = ", ")

0 голосов
/ 16 января 2020

Мы можем group_by ID и использовать setdiff, чтобы получить foods, которого нет в required_foods, и получить его значение через запятую.

library(dplyr)

adf %>% 
   group_by(ID) %>% 
   mutate(missing_foods = toString(setdiff(required_foods, foods)))

#   ID    foods  missing_foods  
#  <fct> <fct>  <chr>          
#1 a     apple  "tomato"       
#2 a     orange "tomato"       
#3 a     banana "tomato"       
#4 b     apple  ""             
#5 b     banana ""             
#6 b     tomato ""             
#7 b     pear   ""             
#8 c     pear   "apple, tomato"
#9 c     onion  "apple, tomato"

То же самое можно сделать и с data.table

library(data.table)
setDT(adf)[, missing_foods := toString(setdiff(required_foods, foods)), ID]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...