Создание одной переменной из списка переменных в R? - PullRequest
7 голосов
/ 22 апреля 2019

У меня есть последовательность переменных в кадре данных (более 100), и я хотел бы создать индикаторную переменную, если в любой из переменных присутствуют определенные текстовые шаблоны. Ниже приведен пример с тремя переменными. Одно решение, которое я нашел, использует tidyr::unite(), за которым следует dplyr::mutate(), но меня интересует решение, в котором мне не нужно объединять переменные.

c1<-c("T1", "X1", "T6", "R5")
c2<-c("R4", "C6", "C7", "X3")
c3<-c("C5", "C2", "X4", "T2")

df<-data.frame(c1, c2, c3)

  c1 c2 c3
1 T1 R4 C5
2 X1 C6 C2
3 T6 C7 X4
4 R5 X3 T2

code.vec<-c("T1", "T2", "T3", "T4") #Text patterns of interest
code_regex<-paste(code.vec, collapse="|")

new<-df %>% 
  unite(all_c, c1:c3, remove=FALSE) %>% 
  mutate(indicator=if_else(grepl(code_regex, all_c), 1, 0)) %>% 
  select(-(all_c))

  c1 c2 c3 indicator
1 T1 R4 C5 1
2 X1 C6 C2 0
3 T6 C7 X4 0
4 R5 X3 T2 1

Выше приведен пример, который дает желаемый результат, однако я чувствую, что должен быть способ сделать это в tidyverse без объединения переменных. Это то, что SAS обрабатывает очень легко, используя оператор ARRAY и цикл DO, и я надеюсь, что у R есть хороший способ справиться с этим.

Реальный информационный фрейм имеет много дополнительных переменных, кроме полей «с» для поиска, поэтому решение, которое включает в себя поиск в каждом столбце, потребует поднабора фрейма данных, чтобы вначале содержались только те переменные, которые я хочу найти, и затем присоединение данных обратно с другими переменными.

Ответы [ 3 ]

6 голосов
/ 22 апреля 2019

Используя базу R, мы можем использовать sapply и grepl, чтобы найти шаблон в каждом столбце и назначить 1 для строк, где найдено более 0 совпадений.

df$indicator <- as.integer(rowSums(sapply(df, grepl, pattern = code_regex)) > 0)

df
#  c1 c2 c3 indicator
#1 T1 R4 C5         1
#2 X1 C6 C2         0
#3 T6 C7 X4         0
#4 R5 X3 T2         1

Если есть несколько других столбцов, и нам интересно применять его только для столбцов, которые начинаются с "c", мы можем использовать grep для их фильтрации.

cols <- grep("^c", names(df))
as.integer(rowSums(sapply(df[cols], grepl, pattern = code_regex)) > 0)

Используя dplyr мы можем сделать

library(dplyr)

df$indicator <- as.integer(df %>%
              mutate_at(vars(c1:c3), ~grepl(code_regex, .)) %>%
              rowSums() > 0)
3 голосов
/ 22 апреля 2019

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

library(tidyverse)
df %>%
    mutate_all(str_detect, pattern = code_regex) %>%
    reduce(`+`) %>% 
    mutate(df, indicator = .)
#  c1 c2 c3 indicator
#1 T1 R4 C5         1
#2 X1 C6 C2         0
#3 T6 C7 X4         0
#4 R5 X3 T2         1

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

Reduce(`+`, lapply(df, grepl, pattern = code_regex))
#[1] 1 0 0 1
1 голос
/ 22 апреля 2019

База R с apply

apply(df[cols], 1, function(x) sum(grepl(code_regex, x)))
# [1] 1 0 0 1
...