读取固定宽度的数据:使用标记定位行

时间:2019-01-11 13:46:11

标签: r tidyverse fixed-width readr

我(应该)具有固定宽度的数据,

134265311
125255388
199265335

我可以这样读取数据

first_ex <- readr::read_fwf("~/example_1.txt", fwf_widths(c(1, 2, 1, 2, 1, 2)))
first_ex
> first_ex
# A tibble: 3 x 6
     X1    X2    X3    X4    X5    X6
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1    34     2    65     3    11
2     1    25     2    55     3    88
3     1    99     2    65     3    35

X1, X3, X5,即原始数据的前几位(1、2和3)是下一列的标记。

现在,我有这样的数据

265311
125388
335

在第一行中缺少带有标记1的数据点,第二行具有标记2的数据点以及第三市场具有市场1和2的数据点丢失。我想找到一种转换数据的方法,如下所示,

> first_ex1
# A tibble: 3 x 6
     X1 X2       X3 X4       X5    X6
  <dbl> <chr> <dbl> <chr> <dbl> <dbl>
1     1 00        2 65        3    11
2     1 25        2 00        3    88
3     1 00        2 00        3    35

任何帮助,建议将不胜感激。

添加

我正在尝试在以下数据集中的l.group <- 16max.index <- 99中实现@建议。索引从10(2位而不是1)开始。

values <- c("1300000190000148200000005000003099000002400001789800000050000030", 
          "1300000190000198290000003000001299000002200002109800000030000012",
          "130000064000011499000006400001149800000000000000",
          "1300000180000129330000003000002199000002100001509800000030000021", 
          "130000025000018099000002500001809800000000000000", 
          "13000001900000633100000020000002480000001000001699000002200000819800000030000018")

我没有想要的输出。例如。如果列标记为13,则对应的列号应为V25和V26。但是我在输出中看到了不同;

enter image description here

如何将代码完美地适合我的数据?

1 个答案:

答案 0 :(得分:1)

怎么样?

library(stringi)
library(data.table)
library(magrittr)

values <- c(265311,
            125388,
            335)

# length of each group, for splitting up
l.group <- 3
# what is the maximum we go up to e.g. 1,2,3 at the moment
max.index <- 3
# NEW: number of digits, has to be same for all
digits <- 1

# make a template
grid <- as.data.table(matrix(sapply(1:max.index, function(x){c(x,0)}), nrow=1))

# split them up from one string
values.split <- trimws(gsub(sprintf("(.{%s})", l.group), "\\1 ", values)) %>%
  stringi::stri_split_regex(., "\\s")

# loop through, append to grid and combine
output <- lapply(values.split, function(x){
  # NEW: made it depend on the digits of index
  index <- as.integer(as.numeric(stringi::stri_sub(x, 1, digits))*2)  
  values <- as.numeric(stringi::stri_sub(x, (digits+1), nchar(x)))
  out <- copy(grid)
  for(i in seq_along(index)) set(out, j=index[i], value=values[i])
  out
}) %>% rbindlist(.)
output[]

使用新的尝试使用digits <- 2