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

时间:2017-08-09 12:58:22

标签: r regex tidyr

我想使用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列?

4 个答案:

答案 0 :(得分:8)

您可以使用基于(?<=[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]))和数字((?=[0-9]))之间。 (?<=...)是一个积极的先行,需要在当前位置的左侧立即存在一些模式,而(?=...)是一个正向前瞻,需要在当前右侧存在其模式地点。因此,分割时字母和数字保持不变。

或者,您可以使用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列):一个或多个数字
  • $ - 字符串结束。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

对于没有基于环视的正则表达式的裸R版本,首先定义正则表达式:

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

然后使用两个substr()命令在匹配的模式之前和之后分离并返回所需的两个组件。

> 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

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

答案 3 :(得分:0)

您可以使用软件包 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创建