分割字符串最后一个分隔符

问题描述 投票:0回答:4

当我在 R 中具有不同数量的相同分隔符时,我需要帮助弄清楚如何根据最后一个分隔符拆分数据框列中的字符串。例如,

col1 <- c('a', 'b', 'c')
col2 <- c('a_b', 'a_b_c', 'a_b_c_d')
df <- data.frame(cbind(col1, col2))

我想拆分 df$col2 以获得一个如下所示的数据框:

col1 <- c('a', 'b', 'c')
col2 <- c('a', 'a_b', 'a_b_c')
col3 <- c('b', 'c', 'd')
r string split delimiter
4个回答
5
投票

使用

stringi
包,您也可以实现您的目标。
stri_extract_last_regex()
提取您在模式中指定的最后一个元素。在这里,我说“获取字符串中的最后一个小字母”。同样,您可以使用
stri_replace_last_regex()
来修改
col2
。这里我说“我想把最后一个模式_和一个小字母什么都替换掉”。也就是说,我说“我想删除最后一个模式_和一个小字母。”

library(dplyr)
library(stringi)

df %>%
mutate(col3 = stri_extract_last_regex(str = col2, pattern = "[a-z]"),
       col2 = stri_replace_last_regex(str = col2, pattern = "_[a-z]", replacement = ""))

#  col1  col2 col3
#1    a     a    b
#2    b   a_b    c
#3    c a_b_c    d

2
投票

这些不使用任何软件包。 他们假设

col2
的每个元素至少有一个下划线。 (如果需要解除此限制,请参阅注释。)

1) 第一个正则表达式

(.*)_
匹配最后一个下划线之前的所有内容,后跟剩余的所有内容
.*
,第一个
sub
将整个匹配项替换为括号内的匹配部分。 这是有效的,因为这样的匹配是贪婪的,所以第一个
.*
会采取一切它可以把剩下的留给第二个
.*
。 第二个正则表达式匹配最后一个下划线之前的所有内容,第二个
sub
将其替换为空字符串。

transform(df, col2 = sub("(.*)_.*", "\\1", col2), col3 = sub(".*_", "", col2))

2) 这是一种更加对称的变体。 它对两个

sub
调用使用相同的正则表达式。

pat <- "(.*)_(.*)"
transform(df, col2 = sub(pat, "\\1", col2), col3 = sub(pat, "\\2", col2))

注意:如果我们确实想处理完全没有下划线的字符串,以便将“xyz”拆分为“xyz”和“”,则将其用于第二个

sub
。 它尝试匹配 | 的左侧首先,如果失败(如果没有下划线就会发生这种情况),那么整个字符串将与右侧匹配,并且
sub
将用空字符串替换它。

sub(".*_|^[^_]*$", "", col2)

2
投票

strsplit
解决方案:

spl <- strsplit(as.character(df$col2), "_")

sapply(lapply(spl, head, -1), paste, collapse="_")
#[1] "a"     "a_b"   "a_b_c"
sapply(lapply(spl, tail, 1), paste, collapse="_")
#[1] "b" "c" "d"

或者疯狂全功能:

Map(
  function(spl,ty,n) sapply(spl, function(x) paste(ty(x,n),collapse="_") ),
  list(strsplit(as.character(df$col2), "_")),
  c(head,tail),
  c(-1,1) 
)
#[[1]]
#[1] "a"     "a_b"   "a_b_c"
#
#[[2]]
#[1] "b" "c" "d"

0
投票

使用

tidyr
包和前瞻正则表达式来确保不再出现分隔符。

col1 <- c('a', 'a', 'b', 'c')
col2 <- c('a', 'a_b', 'a_b_c', 'a_b_c_d')
df <- data.frame(cbind(col1, col2))

df |> 
  tidyr::separate(col2, into = c("col2", "col3"), sep = "_(?!.*_)")
#> Warning: Expected 2 pieces. Missing pieces filled with `NA` in 1 rows [1].
#>   col1  col2 col3
#> 1    a     a <NA>
#> 2    a     a    b
#> 3    b   a_b    c
#> 4    c a_b_c    d

创建于 2024-12-06,使用 reprex v2.1.1

tidyr::separate
包含有用的附加参数,例如如何处理不存在分隔符的情况。

© www.soinside.com 2019 - 2024. All rights reserved.