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 创建
我想使用 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 创建