R 基于模式的一部分在数据框的列中拆分文本
使用R,我试图将具有指定分隔符的列中的文本拆分为两个新列。示例数据框如下所示:R 基于模式的一部分在数据框的列中拆分文本,r,strsplit,R,Strsplit,使用R,我试图将具有指定分隔符的列中的文本拆分为两个新列。示例数据框如下所示: repdf <- data.frame(a=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)"),b=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)")) 我尝试过使用splitstackshape::cSplit和stringr::str_split_fixed但没有效果。 cSplit(repdf,c(“a”、“
repdf <- data.frame(a=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)"),b=c("abc(100)","def(95)","ghi(100)","j_(klm)(100)"))
我尝试过使用splitstackshape::cSplit
和stringr::str_split_fixed
但没有效果。
cSplit(repdf,c(“a”、“b”),“(”)
在每个“(”)处拆分
cSplit(repdf,c(“a”,“b”),“\\([0-9])”,fixed=FALSE)
删除第一个数字,如果可以使用\1
将捕获添加到第二个组中,这会很好,但遗憾的是它不是
a_1 a_2 b_1 b_2
1: abc 00) abc 00)
2: def 5) def 5)
3: ghi 00) ghi 00)
4: j_(klm) 00) j_(klm) 00)
as.data.frame(lapply(repdf,function(x)str_split_fixed(x,“\\(”,n=2))
确实允许我只拆分两列,但当然只需要第一个匹配:
a.1 a.2 b.1 b.2
1 abc 100) abc 100)
2 def 95) def 95)
3 ghi 100) ghi 100)
4 j_ klm)(100) j_ klm)(100)
这就是前瞻派上用场的地方……本质上,我们寻找的是
(
后面跟一个数字\\d
),但前瞻并不使用数字进行拆分
do.call(cbind, lapply(repdf, function(x){
do.call(rbind, strsplit(as.character(x), "\\((?=\\d)", perl = TRUE))
}))
# [,1] [,2] [,3] [,4]
# [1,] "abc" "100)" "abc" "100)"
# [2,] "def" "95)" "def" "95)"
# [3,] "ghi" "100)" "ghi" "100)"
# [4,] "j_(klm)" "100)" "j_(klm)" "100)"
受@Konrad建议的启发,我发现以下内容可用于
tidyr::extract
,但我需要使用其“标准评估版本”tidyr::extract
:
do.call(cbind, lapply(seq_along(repdf),
function(df, i){
tidyr::extract_(data=df[i], col = names(df[i]),
into=c(paste0("tax",i),paste0("prob",i)),
regex = "(.*)\\((?=\\d)(.*)",perl=TRUE)}, df=repdf))
此处的优点是,您可以为拆分的列提供预定义的名称(例如,此处tax
和prob
),这对于下游数据争用非常有用。
另一方面,关于公认答案的有趣之处在于,当数据被拆分成的列数事先未知时(或取决于初始数据帧列的变量),它仍然会像一个符咒一样工作。如前所述,
extract
from可能会提供必要的灵活性。@Konrad,尽管这确实是可能的(例如tidyr::extract(data=repdf,a,into=c('tax','prob'),“(.*)\(?=\\d)(.*”,perl=TRUE)
推断出一个包含多列的data.frame并不是那么容易。@Konrad:你让我思考了一下。当我最初被困在tidyr::extract
的非标准求值版本时,标准求值函数实际上运行得非常优雅。我在下面添加了一个使用它的答案。
do.call(cbind, lapply(repdf, function(x){
do.call(rbind, strsplit(as.character(x), "\\((?=\\d)", perl = TRUE))
}))
# [,1] [,2] [,3] [,4]
# [1,] "abc" "100)" "abc" "100)"
# [2,] "def" "95)" "def" "95)"
# [3,] "ghi" "100)" "ghi" "100)"
# [4,] "j_(klm)" "100)" "j_(klm)" "100)"
do.call(cbind, lapply(seq_along(repdf),
function(df, i){
tidyr::extract_(data=df[i], col = names(df[i]),
into=c(paste0("tax",i),paste0("prob",i)),
regex = "(.*)\\((?=\\d)(.*)",perl=TRUE)}, df=repdf))