замена значений столбца фрейма данных значениями списка и имени списка в R

#r #list #data-cleaning

#r #Список #очистка данных

Вопрос:

Я хотел бы заменить значения внутри столбца именем списка, зависящим от значений, находящихся внутри значений списка:

 df <- data.frame(Activity = c("Checking emails", "Playing games", "Reading", "Watching TV", 
                         "Watching YouTube", "Watching TV", "Relaxing", "Getting ready", 
                         "Working/ studying", "Relaxing"))

mylist <-list(Tech_activity = c("Browsing social media", "Checking emails", 
"Video calling", "On my computer/ PC", "Watching YouTube", "Browsing the internet", 
"On my phone", "Watching TV"), Socialising = c("Spending time with friends", 
"Chatting/ talking/ having a conversation", "Spending time with family"
), Work = "Working/ studying", Transport = c("Travelling", "Walking", 
"Driving"), Household = c("Housework", "Cooking"), Leisure = c("Exercising/ Working out", 
"Getting ready", "Exercising/ working out", "Hobbies eg knitting", 
"Playing games", "Shopping", "Eating", "Listening to music", 
"Reading", "Smoking", "Playing with pets", "Personal caring", 
"Personal care", "Nothing", "Relaxing", "Waiting")) 
 

Итак, если значение фрейма данных находится в значениях элемента в списке, замените df на это имя элемента, если нет, пропустите этот элемент и проверьте следующий элемент списка и так далее. (Пожалуйста, извините за двойной цикл for).

 for (i in df$Activity){
  for (j in mylist){
    if (i %in% mylist[j]){
      i <- names(mylist[j])
    }
  }
}

 

Заранее благодарим вас за любую помощь.

Ответ №1:

Вы можете создать mylist как dataframe, а затем merge использовать его df .

 merge(df, stack(mylist), by.x = 'Activity', by.y = 'values')
 

tidyverse Способ был бы :

 library(tidyverse)

enframe(mylist) %>%
  unnest(value) %>%
  right_join(df, by = c('value' = 'Activity'))

#   name          value            
#   <chr>         <chr>            
# 1 Tech_activity Checking emails  
# 2 Tech_activity Watching YouTube 
# 3 Tech_activity Watching TV      
# 4 Tech_activity Watching TV      
# 5 Work          Working/ studying
# 6 Leisure       Getting ready    
# 7 Leisure       Playing games    
# 8 Leisure       Reading          
# 9 Leisure       Relaxing         
#10 Leisure       Relaxing         
 

Комментарии:

1. Вау, очень полезно, спасибо. Такой перспективы у меня не было

Ответ №2:

В базовом R:

 matches <- unlist(lapply(mylist, function(x) which(df$Activity %in% x)))
df$Activity[matches] <- gsub("\d $", "", names(matches))

df
#>         Activity
#> 1  Tech_activity
#> 2        Leisure
#> 3        Leisure
#> 4  Tech_activity
#> 5  Tech_activity
#> 6  Tech_activity
#> 7        Leisure
#> 8        Leisure
#> 9           Work
#> 10       Leisure
 

Комментарии:

1. Я попытался принять оба ответа, поскольку они правильные и отличные, но это позволит мне сделать только один

2. @ElliotM нет проблем. Выберите тот, который лучше всего отвечает на ваш вопрос.

Ответ №3:

Мы можем использовать tidyverse

 library(tibble)
library(purrr)
library(dplyr)
enframe(mylist, value = 'Activity') %>%
      unnest(c(Activity)) %>%
      inner_join(df)
 

-вывод

 # A tibble: 10 x 2
#   name          Activity         
#   <chr>         <chr>            
# 1 Tech_activity Checking emails  
# 2 Tech_activity Watching YouTube 
# 3 Tech_activity Watching TV      
# 4 Tech_activity Watching TV      
# 5 Work          Working/ studying
# 6 Leisure       Getting ready    
# 7 Leisure       Playing games    
# 8 Leisure       Reading          
# 9 Leisure       Relaxing         
#10 Leisure       Relaxing