You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从自定义格式文本指定行读取数据并转换为data.frame

问题描述

有如下格式的文本文件内容:

DATE                                                                    NETWORK
GROUP ID                          AVERAGE CONC     (YYMMDDHH)             RECEPTOR  (XR, YR, ZELEV, ZHILL, ZFLAG)    OF TYPE  GRID-ID
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
  
ALL      HIGH   1ST HIGH VALUE IS    3822.82070  ON 88011803: AT (  500000.00,  4000150.00,     0.00,     0.00,    0.00)  GC  GRID1   
         HIGH   2ND HIGH VALUE IS    3376.11752  ON 88011803: AT (  500000.00,  4000000.00,     0.00,     0.00,    0.00)  GC  GRID1   
         HIGH   3RD HIGH VALUE IS    2563.76151  ON 88022706: AT (  500200.00,  4000000.00,     0.00,     0.00,    0.00)  GC  GRID1   
         HIGH   4TH HIGH VALUE IS    2033.30514  ON 88010224: AT (  500050.00,  4000050.00,     0.00,     0.00,    0.00)  GC  GRID1   

数据位于文件中间(例如第102839行),需要提取前两行数据,转换为如下结构的data.frame:

SRCGROUP          Value     Conc YYMMDDHH X_coord Y_coord Zelev Zhill ZFLAG
1      ALL 1ST HIGH VALUE 6099.915  8801222  500050 4000050     0     0     0
2      ALL 2ND HIGH VALUE 6001.993 88011801  500100 4000100     0     0     0

目前通过grep定位起始行(row + 9),用readLines读取目标行,但输出是字符向量,无法直接分割为列。尝试过以下代码:

temp <- 
  readLines(file_name)[(row + 9):(row + 9+values_to_read)] 

out <- data.frame(SRCGROUP = temp[,1:9],
                  Value = temp[,15:19],
                  Conc = temp[,33:48],
                  YYMMDDHH = temp[,52:60],
                  X_coord = temp[,66:77],
                  Y_coord = temp[,80:90],
                  Zelev = temp[,91:100],
                  Zhill = temp[,101:110],
                  ZFLAG = temp[,111:119]
                  ) 

现寻求可行解决方案。

解决方案

方法1:使用read.fwf读取固定宽度格式

你的文件属于固定宽度格式,用read.fwf可以直接按列宽读取,无需手动处理字符向量:

# 定义各列的起始和结束位置(根据文本格式调整)
col_positions <- list(
  SRCGROUP = c(1, 9),
  Value = c(15, 31),
  Conc = c(33, 48),
  YYMMDDHH = c(52, 59),
  X_coord = c(66, 77),
  Y_coord = c(80, 90),
  Zelev = c(91, 100),
  Zhill = c(101, 110),
  ZFLAG = c(111, 119)
)
# 转换为列宽向量
col_widths <- sapply(col_positions, function(x) x[2] - x[1] + 1)

# 读取指定行
out <- read.fwf(
  file = file_name,
  widths = col_widths,
  skip = row + 8,  # 跳过目标行之前的所有行
  nrows = values_to_read,
  col.names = names(col_positions),
  strip.white = TRUE  # 自动去除字段前后空格
)

# 清理YYMMDDHH列的冒号,转换数值列类型
out$YYMMDDHH <- gsub(":", "", out$YYMMDDHH)
out[, c("Conc", "X_coord", "Y_coord", "Zelev", "Zhill", "ZFLAG")] <- lapply(out[, c("Conc", "X_coord", "Y_coord", "Zelev", "Zhill", "ZFLAG")], as.numeric)

方法2:处理已读取的字符向量

如果已经通过readLines得到temp字符向量,可使用stringr包提取字段并组合成data.frame:

library(stringr)

# 逐字段提取并清理
out <- data.frame(
  SRCGROUP = str_trim(str_sub(temp, 1, 9)),
  Value = str_trim(str_sub(temp, 15, 31)),
  Conc = as.numeric(str_trim(str_sub(temp, 33, 48))),
  YYMMDDHH = str_trim(str_remove(str_sub(temp, 52, 59), ":")),
  X_coord = as.numeric(str_trim(str_sub(temp, 66, 77))),
  Y_coord = as.numeric(str_trim(str_sub(temp, 80, 90))),
  Zelev = as.numeric(str_trim(str_sub(temp, 91, 100))),
  Zhill = as.numeric(str_trim(str_sub(temp, 101, 110))),
  ZFLAG = as.numeric(str_trim(str_sub(temp, 111, 119)))
)

# 填充第二行及以后的SRCGROUP空值(继承第一行的"ALL")
out$SRCGROUP[out$SRCGROUP == ""] <- out$SRCGROUP[1]

注意:需根据实际文本的列位置微调起始/结束索引,确保截取内容准确。

内容的提问来源于stack exchange,提问作者melmo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 04:34:55