在多个列中使用grepl和ifelse的简便方法

时间:2018-05-14 20:03:08

标签: r

我有这个名为' 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出现,我想创建一个新的二进制变量private,如果跨越相关变量(即job [123] _ [123] _sector),则等于1。然后另一个用于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 :(得分:3)

对于复杂的操作,首先将操作转换为函数然后将其应用于每个案例通常很有用。例如,

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")

答案 1 :(得分:1)

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
...

然后将正则表达式应用于新创建的&#34;扇区&#34;列,可能与summarize一起为每个人和类别获取一个TRUE / FALSE标志:

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

答案 2 :(得分:0)

您可以像这样使用非常强大的(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