我有一个包含约 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
来自 stringi
与 strsplit
拆分后
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/