[英]In R, compare two lists of strings, find parts of each element of the first list on the second
注意:我已更新问题以反映数据中的特定模式。
说我有两个向量。
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级别。 有这么简单的方法吗?
我们可以在保留包含“levels_selected”('grp')中的“names_data”的子字符串之后创建分组变量,使用'grp' split
前缀已删除的子字符串以获取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
model.matrix(~V1+V2-1, d1)
通过使用OP的新例子
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]"
它也使用第一种方法。
如果没有任何字符可以继续“names_data”中的元素,我们可以将它们过滤掉
lst <- strsplit(levels_selected, paste0("(?<=(", paste(names_data,
collapse="|"), "))"), perl = TRUE)
d2 <- as.data.frame(do.call(rbind,lst[lengths(lst)==2]), stringsAsFactors=FALSE)
split(d2$V2, d2$V1)
#$A
#[1] "1" "3"
#$B
#[1] "low" "high"
#$D
#[1] "(4.88e+03,9.18+e+04]"
一个选项,返回一个列表,其中级别为存储在每个相应名称下的向量:
> 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)
所以这是一个方便的小函数我从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>.*)')
搜索此数据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中,所以转换到列表很容易)
这是我对这种东西的全方位,希望它很方便
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.