regex - 我可以使用 tidyr 中的 separator() 或 extract() 将可变长度的数值拆分为其组成数字吗?

标签 regex r dplyr tidyr

我有一个包含约 300 个观测值的数据框,每个观测值都与一个我想拆分为其组成数字的数字代码相关联。代码变量是一个 3 位或 4 位整数,按其最后一位对齐,因此我想要的输出看起来像这样:

code    d4 d3 d2 d1
 403  <NA>  4  0  3 
5123     5  1  2  3
 105  <NA>  1  0  5    

虽然我可以看到很多使用 strsplit 来划分代码的方法(基本 R)或 stringr::str_split ,我很难将这些操作中的任何一个应用于我的数据框。
library(stringr)
as.integer(unlist(str_split(5123, ""))[1]) # returns 5, the first digit - correct
as.integer(rev(unlist(str_split(5123, "")))[1]) # returns 3, the last digit - correct

但合理的(对我来说)操作
libray(dplyr)
df <- data.frame(code = c(403, 5123, 105))
df <- df %>% 
  mutate(
    last = as.integer(rev(unlist(str_split(df$code,"")))[4])
  )

返回
> df
  code last
1  403    3
2 5123    3
3  105    3

显然,我对如何在数据帧内处理列表和原子向量的操作缺乏了解......

然后我确信 separate()extract()来自 tidyr 的函数包会有所帮助。当然,tidyr::separate()如果代码作为字符串提供,每个数字前都有一个前导空格,则会产生所需的结果:
library(tidyr)
dfsep <- data.frame(code = c(" 4 0 3", "5 1 2 3", " 1 0 5"))
dfsep <- dfsep %>% 
  separate(
    code, c("d4", "d3", "d2", "d1"), fill =  "right", remove = FALSE
    )

dfsep
     code d4 d3 d2 d1
1   4 0 3     4  0  3
2 5 1 2 3  5  1  2  3
3   1 0 5     1  0  5

但是一串连续的数字不能用这种方式分割; tidyr::separate() 不支持空搜索模式
df <- data.frame(code = c(403, 5123, 105))
df <- df %>% 
  separate(
    code, c("d4", "d3", "d2", "d1"), fill =  "right", remove = FALSE
  )

df
  code   d4   d3   d2   d1
1  403  403 <NA> <NA> <NA>
2 5123 5123 <NA> <NA> <NA>
3  105  105 <NA> <NA> <NA>

虽然 tidyr::extract() 的问题是因为虽然它很好地提取了数字,但我无法找到一组处理 3 位和 4 位整数的参数:
dfext <- data.frame(code = c(403, 5123, 105))
dfext <- dfext %>% 
  extract(
    code, c("d4", "d3", "d2", "d1"), "(.)(.)(.)(.)", remove = FALSE
    ) 

dfext
  code   d4   d3   d2   d1
1  403 <NA> <NA> <NA> <NA>
2 5123    5    1    2    3
3  105 <NA> <NA> <NA> <NA>

也许我不明白如何为我的目的构建正确的正则表达式代码......

我看过 StackOverflow 上的相关问题,包括这个关于 separate() 的问题。而这个关于extract() ,但我不知道如何将答案应用于我自己的问题。问题here给出具有固定长度值的变量的解,而不是变量。

任何帮助、提示或意见将不胜感激!

附言为了提供上下文,这是一个潜水比赛中的潜水数据框架。每一行代表一次潜水,一个具有多个分组变量的观察:姓名、年龄、性别、潜水编号(例如 5 个中的 1 个)、板高、潜水代码、潜水位置、关税、J1 奖励、J2 奖励、... J5奖、总奖(放弃最高和最低奖)和分数(总奖乘以关税)。代码由 FINA 确定

最佳答案

我们可以使用 stri_list2matrix来自 stringistrsplit 拆分后

n <- max(nchar(df$code)) #get the maximum number of characters
fmt <- paste0('%', n, 'd') #create a format for the `sprintf`
library(stringi)
#the list output from `strsplit` can be coerced to `matrix` using
#stri_list2matrix.
d1 <- stri_list2matrix(strsplit(sprintf( fmt, df$code), ''), byrow=TRUE)
#But, the output is character class, which we can convert to 'numeric' 
m1 <- matrix(as.numeric(d1), ncol=ncol(d1), nrow=nrow(d1))
m1
#     [,1] [,2] [,3] [,4]
#[1,]   NA    4    0    3
#[2,]    5    1    2    3
#[3,]   NA    1    0    5

对于“dfsep”数据集
v1 <- gsub('\\s+', '', dfsep$code)
n <- max(nchar(v1))
fmt <- paste0('%', n, 's')
d1  <- stri_list2matrix(strsplit(sprintf(fmt, v1), ''), byrow=TRUE)
m1 <- matrix(as.numeric(d1), ncol=ncol(d1), nrow=nrow(d1))
m1
#     [,1] [,2] [,3] [,4]
#[1,]   NA    4    0    3
#[2,]    5    1    2    3
#[3,]   NA    1    0    5

我们可以cbind与原始数据集
cbind(dfsep, m1)

这可以做成一个函数,应用于不同的数据集。

关于regex - 我可以使用 tidyr 中的 separator() 或 extract() 将可变长度的数值拆分为其组成数字吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33439538/

相关文章:

r - 当每行是年/站点/区域时为计数创建宽数据

r - 使用 ddply 函数通过 NA 汇总数据

ruby-on-rails - 如果不存在默认协议(protocol),如何在 URL 前面加上默认协议(protocol)?

java - 如何在 Java 中保留分隔符的同时在不同分隔符之间分割文本?

R:在多页的网格布局中绘图

r - 在 R 中绘制来自 tapply 输出的数据

r - 使用 mapply 创建示例时出错

c# - 带有第一个大写字符+数字的正则表达式

后视长度不同的 python 正则表达式 "or"

R dplyr 将多个函数汇总到选定的变量