根据模式的一部分拆分数据框列中的文本
Split text in columns of data frame based upon part of a pattern
使用 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)"))
简而言之,我想在每个开括号“(”处拆分,但前提是它后面跟着一个数字,但不会丢失数字。即所需的结果应该如下所示:
a1 a2 b1 b2
abc 100) abc 100)
def 95) def 95)
ghi 100) ghi 100)
j_(klm) 100) j_(klm) 100)
我曾尝试使用 splitstackshape::cSplit
和 stringr::str_split_fixed
但无济于事。
cSplit(repdf,c("a","b"),"(")
在每个 "("
a_1 a_2 a_3 b_1 b_2 b_3
1: abc 100) NA abc 100) NA
2: def 95) NA def 95) NA
3: ghi 100) NA ghi 100) NA
4: j_ klm) 100) j_ klm) 100)
cSplit(repdf,c("a","b"),"\(([0-9])",fixed=FALSE)
删除第一个数字,如果可以使用 </code> 将捕获添加到第二组那会很好,但遗憾的是它不是。</p>
<pre><code> 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)))
确实允许我只分成 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
),这对下游数据整理很有用。
另一方面,关于已接受答案的有趣之处在于,当事先不知道数据被拆分成的列数(或变量取决于初始数据框列)时,它仍然会像一个魅力一样工作。
使用 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)"))
简而言之,我想在每个开括号“(”处拆分,但前提是它后面跟着一个数字,但不会丢失数字。即所需的结果应该如下所示:
a1 a2 b1 b2
abc 100) abc 100)
def 95) def 95)
ghi 100) ghi 100)
j_(klm) 100) j_(klm) 100)
我曾尝试使用 splitstackshape::cSplit
和 stringr::str_split_fixed
但无济于事。
cSplit(repdf,c("a","b"),"(")
在每个 "("
a_1 a_2 a_3 b_1 b_2 b_3
1: abc 100) NA abc 100) NA
2: def 95) NA def 95) NA
3: ghi 100) NA ghi 100) NA
4: j_ klm) 100) j_ klm) 100)
cSplit(repdf,c("a","b"),"\(([0-9])",fixed=FALSE)
删除第一个数字,如果可以使用 </code> 将捕获添加到第二组那会很好,但遗憾的是它不是。</p>
<pre><code> 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)))
确实允许我只分成 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
),这对下游数据整理很有用。
另一方面,关于已接受答案的有趣之处在于,当事先不知道数据被拆分成的列数(或变量取决于初始数据框列)时,它仍然会像一个魅力一样工作。