tidyr 使用正则表达式将列值分隔为字符和数字

tidyr separate column values into character and numeric using regex

我想使用 tidyr::separate 和正则表达式分隔列值,但我不熟悉正则表达式

df <- data.frame(A=c("enc0","enc10","enc25","enc100","harab0","harab25","harab100","requi0","requi25","requi100"), stringsAsFactors=F) 

这是我试过的

library(tidyr)
df %>%
   separate(A, c("name","value"), sep="[a-z]+")

输出错误

   name value
1           0
2          10
3          25
4         100
5           0
# etc

如何保存 name 列?

您可以将基于 (?<=[a-z])(?=[0-9]) 环视的正则表达式与 tidyr::separate:

结合使用
> tidyr::separate(df, A, into = c("name", "value"), "(?<=[a-z])(?=[0-9])")
    name value
1    enc     0
2    enc    10
3    enc    25
4    enc   100
5  harab     0
6  harab    25
7  harab   100
8  requi     0
9  requi    25
10 requi   100

(?<=[a-z])(?=[0-9]) 模式匹配字符串中小写 ASCII 字母 ((?<=[a-z])) 和数字 ([=17=) 之间的 位置 ]). (?<=...) 是正向前瞻,要求紧邻当前位置左侧存在某种模式,(?=...) 是正向前瞻,要求紧邻当前位置右侧存在其模式地点。因此,拆分时字母和数字保持完整。

或者,您可以使用 extract:

extract(df, A, into = c("name", "value"), "^([a-z]+)(\d+)$")

输出:

    name value
1    enc     0
2    enc    10
3    enc    25
4    enc   100
5  harab     0
6  harab    25
7  harab   100
8  requi     0
9  requi    25
10 requi   100

^([a-z]+)(\d+)$ 模式匹配:

  • ^ - 输入开始
  • ([a-z]+) - 捕获第 1 组(第 name 列):一个或多个小写 ASCII 字母
  • (\d+) - 捕获第 2 组(第 value 列):一位或多位数字
  • $ - 字符串结尾。

如果你真的想通过 separate 获得它,你可以再添加一个步骤,我没有看到这一点,即(使用与@WiktorStribiżew 相同的正则表达式),

df %>% 
  mutate(A = gsub('^([a-z]+)(\d+)$', '\1_\2', A)) %>% 
  separate(A, into = c('name', 'value'), sep = '_')

对于没有 lookaround-based 正则表达式的裸 R 版本,首先定义正则表达式:

> re <- "[a-zA-Z][0-9]"

然后使用两个 substr() 命令来分隔和 return 所需的两个组件,在匹配模式之前和之后。

> with(df,
      data.frame(name=substr(A, 1L, regexpr(re, A)), 
                 value=substr(A, regexpr(re, A) + 1L, 1000L))
      )
    name value
1    enc     0
2    enc    10
3    enc    25
4    enc   100
5  harab     0
6  harab    25
7  harab   100
8  requi     0
9  requi    25
10 requi   100

此处的正则表达式查找模式 "any alpha" [a-zA-Z] 后跟 "any numeric" [0-9]。如果将 sep 参数指定为“”,我相信这就是 reshape 命令的作用。

您可以使用包 unglue

library(unglue)
unglue_unnest(df, A, "{name=\D+}{value}")
#>     name value
#> 1    enc     0
#> 2    enc    10
#> 3    enc    25
#> 4    enc   100
#> 5  harab     0
#> 6  harab    25
#> 7  harab   100
#> 8  requi     0
#> 9  requi    25
#> 10 requi   100

reprex package (v0.3.0)

于 2019-10-08 创建