Grepl 匹配多个条件包括 'and' 和 'or' 条件

Grepl matching for multiple conditions including 'and' and 'or' conditions

我的dataframe如下

df <- data.frame(c("Utility grid", "Grid connection", "Grid", "", "", "Dry-cell-torch", "Solar", ""), c("solar", "", "", "", "", "", "Dry-cell-torch", ""), c("", "fan", "TV", "", "Utility grid connection", "", "", "Unreachable"), c("", "radio", "", "", "", "", "", "")) 
colnames(df) <- c(paste("de_", 1:4, sep=""))

我想将第 5 列 "de" 添加到此数据框,条件如下 -

所需的 "de" 应该是

df$de <- (c(1, 1, 1, 0, 0, 0, 1, 0))

请注意我的原始数据框是 600 行和 45 列。我只是在这里放一个子集,但这个子集说明了我想要完成的详尽条件。

所以我使用 grepl 尝试了以下正则表达式(改编自你们中的一个人在 Whosebug 上针对不同但相似的问题给出的解决方案)-

df$de <- (!grepl("grid|Unreachable|Dry-cell-torch|^$", 
                  apply(df,1,paste, collapse=""), ignore.case=TRUE))+0L

除了在第 1 行中有 "Utility grid",第二列中有 "solar" 的情况外,这有效1.我理解这个问题 - 如果存在网格,无法访问等之一,这应该与同一行中所有其他单元格的 'and' 条件相结合,但我无法弄清楚如何实施这个

感谢您的帮助!

这应该有效。我将默认值设置为 1,然后如果只有空白,或者如果除了 1 之外只有空白,并且这个特殊值适合您的正则表达式,则将该值设置为零。

df <- data.frame(c("Utility grid", "Grid connection", "Grid", "", "", "Dry-cell-torch", "Solar", ""), c("solar", "", "", "", "", "", "Dry-cell-torch", ""), c("", "fan", "TV", "", "Utility grid connection", "", "", "Unreachable"), c("", "radio", "", "", "", "", "", "")) 
colnames(df) <- c(paste("de_", 1:4, sep=""))
df$de <- 1 # default value
blank_rows <- apply(df,1,function(row){sum(row == "")==ncol(df)-1})
regex_rows <- apply(df,1,function(row){sum(row == "")==ncol(df)-2 & any(grepl("grid|Unreachable|Dry-cell-torch|^$", row,ignore.case = TRUE))})
df$de[blank_rows | regex_rows] <- 0

# de_1           de_2                    de_3  de_4 de
# 1    Utility grid          solar                                1
# 2 Grid connection                                    fan radio  1
# 3            Grid                                     TV        1
# 4                                                               0
# 5                                Utility grid connection        0
# 6  Dry-cell-torch                                               0
# 7           Solar Dry-cell-torch                                1
# 8                                            Unreachable        0

考虑明确拆分条件:

f <- function(x) {
  if ( all(x == '') ) 0
  else if ( sum(x != '') == 1 ) {
    if ( grepl('grid', tolower(x[x != ''])) |
         (x[x != ''] %in% c('Unreachable', 'Dry-cell-torch')) ) 0
    else 1
  } 
  else 1
}

然后使用应用apply(df, 1, f)

我好像得到了你想要的向量:

> apply(df, 1, f)
[1] 1 1 1 0 0 0 1 0

更新:

可以使用另一个参数来索引您想要在 f 中的特定列。请注意,这不是一个可靠的实现——设置错误的列会破坏它。

f <- function(x, columns) {

  y <- x[columns]

  if ( all(y == '') ) 0
  else if ( sum(y != '') == 1 ) {
    if ( grepl('grid', tolower(y[y != ''])) |
         (y[y != ''] %in% c('Unreachable', 'Dry-cell-torch')) ) 0
    else 1
  } 
  else 1
}

然后使用应用apply(df, 1, f, columns = 1:4)。只需将 1:4 替换为您想要的列即可。

更新二:

不确定我是否完全理解你最近的评论,但如果你想考虑多个 "special" 单元格,你可以考虑以下结构(虽然我不确定它是否会更多"elegant" 比你试过的要好):

f <- function(x, columns) {

  y <- x[columns]

  n.not.blank <- sum( y != '' )
  special <- c('Unreachable', 'Dry-cell-torch')
  n.special <- sum( grepl('grid', tolower(y)) | (y %in% special) )

  if (n.not.blank == 0) 0
  else if (n.not.blank == n.special) 0
  else 1

}

然后像以前一样使用apply。