【问题标题】:Separating characters by a delimiter into vectors assuming fixed width通过分隔符将字符分隔为假定固定宽度的向量
【发布时间】:2019-06-14 02:59:58
【问题描述】:

我有以下字符数据,

v1 <- c("1321-56, 21-, 15-, 1701-13,", "1305-25, 2101-03, 1501-02, 1711-55,", "1309-18, 21-, 1501-04, 1701-15,")
data <- data.frame(v1)
> data
                                   v1
1         1321-56, 21-, 15-, 1701-13,
2 1305-25, 2101-03, 1501-02, 1711-55,
3     1309-18, 21-, 1501-04, 1701-15,

用逗号分隔,每行字符被分成3个部分。字符编号应分别为 2、5 和 6。例如,

  • 1321-56 应分布为三个向量,如 13(2 个字符)、00021(5 个字符)和 000056(6 个字符)。
  • 15- 应该分布到三个向量中,例如 15, 00000000000。等等。

最终的输出应该是这样的,

> data1
  v1a   v1b    v1c v2a   v2b    v2c v3a   v3b    v3c v4a   v4b    v4c
1  13 00021 000056  21 00001 000000  15 00000 000000  17 00001 000013
2  13 00005 000025  21 00001 000003  15 00000 000000  17 00011 000055
3  13 00009 000018  21 00000 000000  15 00000 000000  17 00001 000015

知道怎么做吗?

【问题讨论】:

  • 总是有 4 个组吗? (v1v4
  • 尝试在stringi 中添加stri_sub 的0?
  • 好点。答案是不。它可以是两个不连续的数字,范围从 01 到 99。@JuliusVainora
  • 但它是所有行的共同数字,对吧?
  • 是的,例如标记132115 将位于下一行的相同位置。 @朱利叶斯维诺拉

标签: r regex tidyverse tidyr


【解决方案1】:

下面是str_matchsprintf 的两步方法。首先我们拆分所有内容:

n <- 4 # or str_count(v1, ",")[1] of it's common to all the rows
(M <- str_match(v1, paste0(rep("(\\d{2})(\\d*)-(\\d*)[, ]*", n), collapse = ""))[, -1])
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
# [1,] "13" "21" "56" "21" ""   ""   "15" ""   ""   "17"  "01"  "13" 
# [2,] "13" "05" "25" "21" "01" "03" "15" "01" "02" "17"  "11"  "55" 
# [3,] "13" "09" "18" "21" ""   ""   "15" "01" "04" "17"  "01"  "15" 

给出3 * n 列,然后用sprintf 格式化矩阵:

matrix(sprintf(c("%02s", "%05s", "%06s"), t(M)), nrow = nrow(M), byrow = TRUE)
#      [,1] [,2]    [,3]     [,4] [,5]    [,6]     [,7] [,8]    [,9]     [,10] [,11]   [,12]   
# [1,] "13" "00021" "000056" "21" "00000" "000000" "15" "00000" "000000" "17"  "00001" "000013"
# [2,] "13" "00005" "000025" "21" "00001" "000003" "15" "00001" "000002" "17"  "00011" "000055"
# [3,] "13" "00009" "000018" "21" "00000" "000000" "15" "00001" "000004" "17"  "00001" "000015"

【讨论】:

  • 简单、简短、智能。谢谢你。我正在用更简单的数据练习你的想法。我有一个错误,我在原始问题中添加了它。知道我在这里做错了什么吗?
  • @ome,我没有验证输出是否是您想要的,但问题在于使用easy;你需要传递一个向量,例如,easy[, 1]
  • @ome,没问题。我还删除了您的更新,因为它不是最初问题的一部分。
【解决方案2】:

假设所有输入子字符串的格式为9999-99,99-,,我们使用一个gsub 将第一个格式转换为三个空格分隔的字段,另一个gsub 将第二个格式转换为三个空格分隔的字段字段。最后read.table 从中生成一个数据框。如果列名无关紧要,则可以省略 col.names= 参数。没有使用任何包。

s <- gsub("(\\d\\d)(\\d\\d)-(\\d\\d),", "\\1 000\\2 0000\\3", data$v1)
s2 <- gsub("(\\d\\d)-,", "\\1 00000 000000", s)
read.table(text = s2, colClasses = "character", 
  col.names = paste0("v", rep(1:4, each = 3), letters[1:3]))

给予:

  v1a   v1b    v1c v2a   v2b    v2c v3a   v3b    v3c v4a   v4b    v4c
1  13 00021 000056  21 00000 000000  15 00000 000000  17 00001 000013
2  13 00005 000025  21 00001 000003  15 00001 000002  17 00011 000055
3  13 00009 000018  21 00000 000000  15 00001 000004  17 00001 000015

easy例子

关于easy 示例,请注意问题中定义easy 的行中的第二个&lt;- 应该是=。进行修复并假设每个子字符串将使用第一列的前两位数字拆分为两列,然后将其余数字拆分为下一列:

s <- gsub("(\\d\\d)(\\d*),", "\\1,\\2,", easy$v1)
read.table(text = s, colClasses = "character", sep = ",")[-15]

给予;

  V1   V2  V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14
1 01 0718  02    03    04 16 05  11  06      07    
2 01 0819  02 11 03 22 04  2 05  21  06   2  07  21
3 01 0819  02  1 03  2 04  6 05   1  06  11  07  01

【讨论】:

    猜你喜欢
    • 2020-04-18
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    相关资源
    最近更新 更多