R数据帧中基于正则表达式的字符串重新映射

时间:2017-02-28 20:32:48

标签: r dataframe vectorization

我正在尝试通过循环遍历其他数据帧中定义的正则表达式来清除某些数据帧中混乱的自由格式捕获的字符串。例如:

id <- c(1, 2, 3, 4) 
text <- c(NA, "messy1 messy2", "MESSY2,,, messy1", "ignore")
df <- data.frame(id, text)

mapin <- c("messy1", "messy2")
mapout <- c("Clean 1", "Clean 2")
map <- data.frame(mapin, mapout)

cout <- c(NA, "Clean 1, Clean 2", "Clean 1, Clean 2", NA)

我想通过正则表达式df$cout中的匹配标记(忽略大小写)创建新列map$mapin,并在连接字符串中从map$mapout输出相应的已清理标记,其中输出标记按字母顺序排序。在我看来,凌乱的数据帧列上的复制/正则表达式替换会更加痛苦,因为所有其他非匹配的东西都必须以某种方式被丢弃。

任何人都可以看到一个好的 R / vectorised / 非hammy 这样做的方法吗?

2 个答案:

答案 0 :(得分:1)

使用stri_extract_all中的stringi - 包:

library(stringi)
m1 <- sapply(map$mapin, function(x) stri_extract_all_fixed(tolower(df$text), x))
m2 <- matrix(map$mapout[match(m1, map$mapin)], ncol = nrow(map))

vec <- apply(m2, 1, function(x) paste(na.omit(x), collapse = ", ") )
vec[vec == ''] <- NA

df$cout <- vec

你得到:

> df
  id             text             cout
1  1             <NA>             <NA>
2  2    messy1 messy2 Clean 1, Clean 2
3  3 MESSY2,,, messy1 Clean 1, Clean 2
4  4           ignore             <NA>

答案 1 :(得分:0)

根据@ Jaap的优秀答案,在我的问题域中进行了一些调整,但这些调整可能对其他人来说很常见&#39;挑战:

  1. 创建矩阵m2时动态确定地图的大小。

  2. 对输出标记进行一致排序。

  3. 使用stri_extract_first_fixed对重复的输入令牌不敏感。

  4. 完整示例:

    # Problem
    id <- c(1, 2, 3, 4) 
    text <- c(NA, "messy1 messy2", "MESSY2,,, messy1,messy1", "ignore")
    df <- data.frame(id, text)
    mapin <- c("messy2", "messy1")
    mapout <- c("Clean 2", "Clean 1")
    map <- data.frame(mapin, mapout)
    
    # Solution
    m1 <- sapply(map$mapin, function(x) stri_extract_first_fixed(tolower(df$text), x))
    m2 <- matrix(map$mapout[match(m1, map$mapin)], ncol = nrow(map))
    vec <- apply(m2, 1, function(x)
        paste0(c(unique(sort(x, na.last = NA)), use.names = FALSE), collapse = ", "))
    vec[vec==''] <- NA
    df$clean <- vec
    

    Per @ r2evans&#39;上面的评论,如果您需要正则表达式,只需将stri_extract_first_fixed替换为stri_extract_first_regex