我想使用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
列?
答案 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创建