Превращение нескольких строковых шаблонов в двоичные столбцы - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь превратить определенные строковые шаблоны в двоичные столбцы для трех различных столбцов, используя язык программирования R .

Вот что у меня есть:

have <- structure(list(rep1 = c("china", "na", "bay", "eng", "giad", 
"china", "sing", "giad", "na", "china", "china, camp", "guat,camp", 
"na", "na", "cis", "trans", "stron, mon"), rep2 = c("china", 
"na", "bay", "eng", "giad", "china", "sing", "giad", "na", "china", 
"china, camp", "camp", "na", "na", "cis", "trans", "stron, mon"
), rep3 = c("na", "na", "bay", "eng", "giad", "china", "sing", 
"giad", "china", "china", "china, camp", "camp", "na", "na", 
"cis", "trans", "stron, mon")), row.names = c(NA, -17L), class = c("data.table", 
"data.frame"))

А вот что я хочу:

    want <- structure(list(rep1 = c("china", "na", "bay", "eng", "giad", 
"china", "sing", "giad", "na", "china", "china, camp", "guat,camp", 
"na", "na", "cis", "trans", "stron, mon"), rep2 = c("china", 
"na", "bay", "eng", "giad", "china", "sing", "giad", "na", "china", 
"china, camp", "camp", "na", "na", "cis", "trans", "stron, mon"
), rep3 = c("na", "na", "bay", "eng", "giad", "china", "sing", 
"giad", "china", "china", "china, camp", "camp", "na", "na", 
"cis", "trans", "stron, mon"), rep1_chi = c(1, 0, 0, 0, 0, 1, 
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0), rep2_chi = c(1, 0, 0, 0, 0, 
1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0), rep3_chi = c(0, 0, 0, 0, 
0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0), rep1_bay = c(0, 0, 1, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep2_bay = c(0, 0, 
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep3_bay = c(0, 
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep1_gia = c(0, 
0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep2_gia = c(0, 
0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep3_gia = c(0, 
0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep1_sin = c(0, 
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep2_sin = c(0, 
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), rep3_sin = c(0, 
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), class = "data.frame", row.names = c(NA, 
-17L))

Мне удалось создать рабочее решение, используя ifelse и stringr::str_detect следующим образом:

want <- have %>% dplyr::select(rep1, rep2, rep3) %>% mutate(
      rep1_chi = ifelse(str_detect(rep1,"chi") == T,1,0),
      rep2_chi = ifelse(str_detect(rep2,"chi") == T,1,0),
      rep3_chi = ifelse(str_detect(rep3,"chi") == T,1,0),
      rep1_bay = ifelse(str_detect(rep1,"bay") == T,1,0),
      rep2_bay = ifelse(str_detect(rep2,"bay") == T,1,0),
      rep3_bay = ifelse(str_detect(rep3,"bay") == T,1,0),          
      rep1_gia = ifelse(str_detect(rep1,"gia") == T,1,0),
      rep2_gia = ifelse(str_detect(rep2,"gia") == T,1,0),
      rep3_gia = ifelse(str_detect(rep3,"gia") == T,1,0),           
      rep1_sin = ifelse(str_detect(rep1,"sin") == T,1,0),
      rep2_sin = ifelse(str_detect(rep2,"sin") == T,1,0),
      rep3_sin = ifelse(str_detect(rep3,"sin") == T,1,0))

Моя самая большая проблема в том, что это кажется довольно повторяющимся. Мне было интересно, есть ли более элегантное решение? Учитывая, что столбцы "rep" имеют числовой порядок 1-3, я подумал, что может быть лучший способ это запрограммировать.

Просматривая SO, я нашел следующее решение с использованием model.matrix, которое, кажется, работает хорошо, когда вы хотите каждый шаблон и заинтересованы только в одном столбце. Я попытался превратить это в функцию, чтобы выбрать несколько столбцов, но мне все равно пришлось бы удалять строки с шаблонами, которые не представляют интереса.

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Вот некрасивый и неэффективный (с точки зрения производительности) базовый код, в котором вам не нужно самим создавать имена столбцов:

want_new <- have
colold <- colnames(want_new)
for (p in pattern) {
  cname <- paste0(
    colold, 
    "_",
    p
  )
  for (col in cname) {
    want_new[, col] <- as.numeric(str_detect(
      want_new[, gsub(paste0("_", p), "", col, fixed)],
      p
    ))
  }
}

Уверен, что это можно улучшить, немного доработав.

0 голосов
/ 18 января 2019

Вот подход, использующий mutate_all. Если вы хотите сделать это только для определенных столбцов, вы просто должны использовать mutate_at и указать вместо них столбцы.

library(dplyr)
library(stringr)

mutate_all(have, funs(chi = as.numeric(str_detect(., "chi")),
                  bay = as.numeric(str_detect(., "bay")),
                  gia = as.numeric(str_detect(., "gia")),
                  sin = as.numeric(str_detect(., "sin"))))

mutate_at пример с vars:

want <- have %>% mutate_at(vars(rep1,rep2,rep3), funs( 
                           tox = as.numeric(str_detect(., "chi")), 
                           bay = as.numeric(str_detect(., "bay")), 
                           gia = as.numeric(str_detect(., "gia")), 
                           iso = as.numeric(str_detect(., "sin"))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...