более простой способ использовать grepl и ifelse в нескольких столбцах - PullRequest
0 голосов
/ 14 мая 2018

У меня есть этот набор данных с именем 'jobdata'

 names <- c("person1", "person2", "person3")
 job1_1_sector <- c("Private", "Public", "Private")
 job2_1_sector <- c(NA, "Public", "Private")
 job2_2_sector <- c("Private", "Public", "Other")
 job3_1_sector <- c("Private", "Private", "Private")
 job3_2_sector <- c("Other", "Public", "Other")
 job3_3_sector <- c("Private", NA, "Private")
 jobs <- cbind(job1_1_sector, job2_1_sector, job2_2_sector, job3_1_sector, 
 job3_2_sector, job3_3_sector )

 jobdata <- data.frame(names, jobs)

И я хочу создать новую двоичную переменную private, которая равняется 1, если по соответствующим переменным (то есть заданию [123] _ [123] _sector), если появляется слово Private. Затем еще один для Public и еще один для Other. Я понял, как использовать это с ifelse и grepl, но похоже, что мои строки кода действительно длинные. Есть ли более простой способ сделать это?

Этот код ниже дает мне код, который я хочу:

 jobdata$private <- ifelse(grepl("Private", jobdata$job1_1_sector) | grepl("Private", jobdata$job2_1_sector) | grepl("Private", jobdata$job2_2_sector) | grepl("Private", jobdata$job3_1_sector) | grepl("Private", jobdata$job3_2_sector) | grepl("Private", jobdata$job3_3_sector), 1, 0)

 jobdata$public <- ifelse(grepl("Public", jobdata$job1_1_sector) | grepl("Public", jobdata$job2_1_sector) | grepl("Public", jobdata$job2_2_sector) | grepl("Public", jobdata$job3_1_sector) | grepl("Public", jobdata$job3_2_sector) | grepl("Public", jobdata$job3_3_sector), 1, 0) 

 jobdata$other <- ifelse(grepl("Other", jobdata$job1_1_sector) | grepl("Other", jobdata$job2_1_sector) | grepl("Other", jobdata$job2_2_sector) | grepl("Other", jobdata$job3_1_sector) | grepl("Other", jobdata$job3_2_sector) | grepl("Other", jobdata$job3_3_sector), 1, 0) 

Спасибо!

Ответы [ 3 ]

0 голосов
/ 14 мая 2018

Вы можете использовать очень мощное семейство (s)apply, например:

# define the types
type <- c("Private", "Public", "Other")

# columns in question
mask <- grepl("^job\\d+_\\d+_sector", colnames(jobdata))

# apply(..., 1, ...) means row-wise
jobdata[type] <- t(apply(jobdata[mask], 1, function(x) {
  (s <- sapply(type, function(y) {
    as.numeric(y %in% x)
  }))
}))

Это дает

    names job1_1_sector job2_1_sector job2_2_sector job3_1_sector job3_2_sector job3_3_sector Private Public Other
1 person1       Private          <NA>       Private       Private         Other       Private       1      0     1
2 person2        Public        Public        Public       Private        Public          <NA>       1      1     0
3 person3       Private       Private         Other       Private         Other       Private       1      0     1
0 голосов
/ 14 мая 2018
Решение

A tidyverse / dplyr заключается в том, чтобы сначала объединить множество столбцов заданий в единый набор меток и значений:

library(tidyverse)

jobdata.long <- jobdata %>% 
  gather(job.number, sector, -names)

     names    job.number  sector
1  person1 job1_1_sector Private
2  person2 job1_1_sector  Public
3  person3 job1_1_sector Private
4  person1 job2_1_sector    <NA>
5  person2 job2_1_sector  Public
6  person3 job2_1_sector Private
7  person1 job2_2_sector Private
8  person2 job2_2_sector  Public
9  person3 job2_2_sector   Other
...

А затем примените ваши регулярные выражения к вновь созданному столбцу "сектор", возможно, в тандеме с summarize, чтобы получить один флаг ИСТИНА / ЛОЖЬ для каждого человека и категории:

job.types <- jobdata.long %>% 
  group_by(names) %>% 
  summarize(
    private = any(grepl('Private', sector)),
    public = any(grepl('Public', sector)),
    other = any(grepl('Other', sector))
  )

    names private public other
   <fctr>   <lgl>  <lgl> <lgl>
1 person1    TRUE  FALSE  TRUE
2 person2    TRUE   TRUE FALSE
3 person3    TRUE  FALSE  TRUE
0 голосов
/ 14 мая 2018

Для сложных операций часто бывает полезно сначала превратить операцию в функцию, а затем применить ее к каждому случаю. Например,

get_sector <- function(x, sector) {
  apply(x, 1, function(y) {
    as.numeric(any(grepl(sector, y), na.rm = TRUE))
  })
}

jobdata$private <- get_sector(jobdata, "Private")
jobdata$public <- get_sector(jobdata, "Public")
jobdata$other <- get_sector(jobdata, "Other")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...