Слово поиска во фрейме данных, имя возвращаемого столбца? - PullRequest
1 голос
/ 29 января 2020

I w * sh для поиска по фрейму данных (на самом деле, по списку слов по категориям), и, если слово найдено, возвращается имя столбца; если он не найден, он просто воспроизводит слово. Основная идея c приведена ниже, но я не могу заставить ее работать должным образом:


#data frame to be searched
words <- data.frame(people=c("Mike", "Tom", "Molly", "Susan"),
           dogs=c("Rex", "Fido", "King", "Roy"))

#data frame to work with
d <- data.frame(name=c("Roy","Tom", "Pat"))

d %>% mutate(
  returned = ifelse(name %in% d, colnames(), name)
)

Это возвращает:

  name returned
1  Roy        2
2  Tom        3
3  Pat        1

Однако, оно должно вернуть

  name returned
1  Roy        dog
2  Tom        people
3  Pat        Pat

Я чувствую, что мой сценарий близок, но не уверен, что нужно сделать, чтобы это исправить. Любая помощь приветствуется!

Ответы [ 2 ]

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

Числа в 'возвращенном' являются результатом приведения factor к значениям режима хранения integer. Этого можно избежать, если мы создадим столбец класса character с stringsAsFactors = FALSE при создании data.frame или используем as.character(name).

d <- data.frame(name=c("Roy","Tom", "Pat"), stringsAsFactors = FALSE)
words <- data.frame(people=c("Mike", "Tom", "Molly", "Susan"),
       dogs=c("Rex", "Fido", "King", "Roy"), stringsAsFactors = FALSE)

В дополнение к проблеме с factor, код OP в ifelse не использует набор данных keyvalue 'words', т.е. name %in% d относится к вызову значения столбца 'name' в data.frame, а второй аргумент - colnames(), что привело бы к «ошибке», но поскольку первое выражение возвращает FALSE, оно проверит значения «no», т. е. «name»

d %>%
    mutate(i1 =  name %in% d)
#  name    i1
#1  Roy FALSE
#2  Tom FALSE
#3  Pat FALSE

Поскольку 'name' равно factor, его значения приводятся к целочисленному режиму, и это то, что отображается в выходных данных


Мы можем использовать pivot_longer для преобразования в 'long' формат, а затем сделать right_join

library(dplyr)
library(tidyr)
words %>%
     pivot_longer(everything()) %>%
     right_join(d, by = c('value' = 'name')) %>%
     mutate(name = ifelse(is.na(name), value, name)) %>%
     select(returned = name, name = value)
#   returned name
#1     dogs  Roy
#2   people  Tom
#3      Pat  Pat

Или мы можем использовать case_when без какого-либо изменения

d %>%
   mutate(returned = case_when(name %in% words$people ~ 'people',
                      name %in% words$dogs ~ 'dogs', 
                      TRUE ~ as.character(name)))
#   name returned
#1  Roy     dogs
#2  Tom   people
#3  Pat      Pat

Или используя только base R

d$returned <- with(stack(words), as.character(ind[match(d$name, values)]))
d$returned[is.na(d$returned)] <- d$name[is.na(d$returned)]
d
#  name returned
#1  Roy     dogs
#2  Tom   people
#3  Pat      Pat
2 голосов
/ 29 января 2020

Мы можем получить words данные в длинном формате и затем сделать left_join. Для возвращаемых значений, которые не совпадают, мы можем заменить значение name.

library(dplyr)
d %>%
  left_join(tidyr::pivot_longer(words, cols = names(words), names_to = 'returned'), 
            by = c('name' = 'value')) %>%
  mutate(returned = coalesce(returned, name))

#  name returned
#1  Roy     dogs
#2  Tom   people
#3  Pat      Pat
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...