按大小写拆分字符串

Splitting strings by case

我有一个基于文本的大型数据框(大约 10 万行),其中每一行都是一个字符串,其中包含第一个小写字母,然后是大写字母,中间有空格。如下图:

df1 <- data.frame(a = c('lowercase U P P E R C A S E', 'letters N U M B E R S'), 
                  stringsAsFactors = FALSE)
df1

我试图在字符串变成大写的地方拆分字符串,并将大写字符移到新列中(从而将它们从原始列中删除)。所需的输出将如下所示:

df2 <- data.frame(a = c('lowercase', 'letters'),
                  b = c('U P P E R C A S E', 'N U M B E R S'),
                  stringsAsFactors = FALSE)
df2

说实话,我不确定从哪里开始做这样的事情。有什么想法吗?

我们可以使用tidyr::extract

tidyr::extract(df1, a, c("a", "b"), "([a-z]+)([A-Z\s]+)")

#          a                  b
#1 lowercase  U P P E R C A S E
#2   letters      N U M B E R S

有很多不同的方法可以做到这一点,但绝大多数会使用 Regular Expressions

在基础 R 中,你可以这样做:

df3 <- data.frame(
         a = gsub(pattern = "^([a-z]+) (([A-Z] )*[A-Z])$", replacement = "\1", x = df1$a),
         b = gsub(pattern = "^([a-z]+) (([A-Z] )*[A-Z])$", replacement = "\2", x = df1$a),
         stringsAsFactors = FALSE)

这里,gsub函数在第一组([a-z]+)中捕获小写字母,然后在第二组(([A-Z] )*[A-Z])中捕获交替的大写字母和spaces ].然后它用 a 列的第一组内容和 b 列的第二组内容替换整个字符串。

另一种方法,这次使用前瞻和后视,以及 tidyr 包中的 separate 函数:

df4 <- tidyr::separate(df1, 
                       col = a, 
                       into = c("a", "b"), 
                       sep = "(?<=[a-z]) (?=[A-Z])")

在这里,(?<=[a-z]) 是一个将匹配任何小写字母的后视,而 (?=[A-Z]) 是一个将匹配任何大写字母的前视。因为向前看和向后看之间有一个space,它会用第一个 space 分隔字符串,这个 space 紧接在小写字母之后和紧接在大写字母之前,它表征了 space 分隔您要创建的两列。