在R中,比较两个字符串列表,找到第二个

时间:2016-05-15 04:24:54

标签: r subset

注意:我已更新问题以反映数据中的特定模式。

说我有两个向量。

   names_data <- c('A', 'B', 'C', 'D', 'E', 'F')
   levels_selected <- c('A1','A3', 'Blow', 'Bhigh', 'D(4.88e+03,9.18+e+04]', 'F')

我想知道如何获取向量,数据框,列表或其他任何内容,检查水平向量并返回选定的变量的哪个级别。有些话说:

    A: 1, 3
    B: low, high
    D: (4.88e+03,9.18e+04]

最终,有一个数据框X,其中names_data = names(data)levels_selected是每个变量中某些(但不是全部)等级的数据。最后,我想要做的是使用model.matrix制作一个矩阵(例如,一个随机森林),我只想在levels_selected中包含变量AND级别。有这么简单的方法吗?

3 个答案:

答案 0 :(得分:1)

我们可以在“levels_selected”('grp')中保留包含“names_data”的子字符串后创建分组变量,split使用'grp'删除前缀的子字符串来获取{{ 1}}。

list

如果我们的意思是

grp <- sub(paste0("^(", paste(names_data, collapse="|"), ").*"), "\\1", levels_selected)
value <- gsub(paste(names_data, collapse="|"), "", 
               levels_selected)
lst <- split(value, grp)
lst
#$A
#[1] "1" "3"

#$B
#[1] "low"  "high"

#$D
#[1] "x"

或另一种选择是使用library(qdapTools) mtabulate(lst) # 1 3 high low x #A 1 1 0 0 0 #B 0 0 1 1 0 #D 0 0 0 0 1

strsplit

可能d1 <- as.data.frame(do.call(rbind, strsplit(levels_selected, paste0("(?<=(", paste(names_data, collapse="|"), "))"), perl=TRUE)), stringsAsFactors=FALSE) aggregate(V2~V1, d1, FUN= toString) # V1 V2 #1 A 1, 3 #2 B low, high #3 D x 将是

model.matrix

更新

使用OP的新示例

model.matrix(~V1+V2-1, d1)

它也在使用第一种方法。

UPDATE2

如果没有任何字符可以继续“names_data”中的元素,我们可以将它们过滤掉

d1 <- as.data.frame(do.call(rbind, strsplit(levels_selected,
  paste0("(?<=(", paste(names_data, collapse="|"), "))"), 
         perl=TRUE)), stringsAsFactors=FALSE)
split(d1$V2, d1$V1) 
#$A
#[1] "1" "3"

#$B
#[1] "low"  "high"

#$D
#[1] "(4.88e+03,9.18+e+04]"

答案 1 :(得分:0)

一个选项,它返回一个列表,其中包含存储在每个相应名称下的向量:

> setNames(lapply(names_data, function(x) gsub(x, "", levels_selected[grepl(x, levels_selected)])), names_data)
$A
[1] "1" "3"

$B
[1] "low"  "high"

$C
character(0)

$D
[1] "x"

$E
character(0)

答案 2 :(得分:0)

所以这是一个方便的小函数我从regexpr帮助示例扩展,使用perl风格的正则表达式

parseAll <- function(data, pattern) {

  result <- gregexpr(pattern, data, perl = TRUE)
  do.call(rbind,lapply(seq_along(data), function(i) {
  if(any(result[[i]] == -1)) return("")
  st <- data.frame(attr(result[[i]], "capture.start"))
  le <- data.frame(attr(result[[i]], "capture.length") - 1)

  mapply(function(start,leng) substring(data[i], start, start + leng), st, le)

}))
}

编辑:它已经扩展,因为这个将找到模式的多个匹配,允许您查找每行多个模式。所以像这样的模式:"(?<first>[[:upper:]][[:lower:]]+) (?<last>[[:upper:]][[:lower:]]+)"(来自原始的regexpr帮助)在每个字符串中找到模式的所有实例,而不仅仅是一个。

假设我的数据看起来像这样:

dat <- c('A1','A2','A3','B3')

然后我可以通过搜索这些数据 parseAll(z,'A(?<A>.*)|B(?<B>.*)')获取具有所选级别的data.frame:

parseAll(dat,'A(?<A>.*)|B(?<B>.*)')

     A   B  
[1,] "1"  "" 
[2,] "2"  ""
[3,] "3"  "" 
[4,] ""   "3" 

哪个选择具有每个级别(虽然这可能对您没用),我也可以从您的向量中以编程方式生成这些模式:

pattern <- paste(paste0(names_data,'(?<',names_data,'>.*)'),collapse = '|')

然后您选择的级别是每列的唯一元素(它在data.frame中,因此转换到列表很容易)

这是我对这种东西的全方位,希望它很方便