如何将不规则/暗示的数据读入r中

3
如何读取以下示例中的数据?(我的实际文件类似于ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/Operational/2012/AL182012/1030/0730/AL182012_1030_0730.gz,格式为http://www.aoml.noaa.gov/hrd/Storm_pages/grid.html--它们看起来像Fortran隐含循环写入)。我的问题是文件中有多个标题和向量,每行的值不同。对于.gz文件,扫描似乎从开头开始,而我希望读取逐步解析文件。
This is a headerline with a name.  
The fourth line has the number of elements in the first vector,
and the next vector is encoded similarly
7
1 2 3
4 5 6
7
8
1 2 3 
4 5 6
7 8

这不像我想要的那样工作:

fh<-gzfile("junk.gz")
headers<-readLines(fh,3)
nx<-as.numeric(readLines,1)
x<-scan(fh,nx) 
ny<-as.numeric(readLines,1)
y<-scan(fh,ny)

这样做有点效果,但我还需要计算跳过的值:
...
x<-scan(fh,skip=3,nx)
...

啊...我发现使用gzfile()打开文件不能对数据进行搜索操作,所以所有的scan()函数都会重新开始并从文件开头开始。如果我解压缩文件并对未压缩的数据进行操作,我可以使用readLines(fh,n)和scan(fh,n=n)逐步读取各个部分。

readVector<-function(fh,skip=0,what=double()){ 
  if (skip !=0 ){junk<-readLines(fh,skip)}
  n<-scan(fh,1)
  scan(fh,what=what,n=n)
}

fh<-file("junk")
headers<-readLines(fh,3)
x<-readVector(fh) 
y<-readVector(fh)
xl<-readVector(fh) 
yl<-readVector(fh) 
...  # still need to process a parenthesized complex array, but that is a different problem.

你完成后希望数据有什么样的结构? - Thomas
你实际链接的文件似乎有多种类型的数据。 "表面风分量" 的识别方式不同(看起来是括号内的数字对)。你实际想要什么数据,你正在寻找什么最终格式,所有文件的结构是否大致相同? - A5C1D2H2I1M1N2O1R2T1
抱歉,没看到你的编辑。也可能可以通过使用grep来协助处理。 - A5C1D2H2I1M1N2O1R2T1
1个回答

1
看几个样本文件,似乎只需要确定读取一次的数字,然后可以用于处理文件的所有部分。
如我在评论中提到的,grep 可以帮助自动化该过程。这是我想出来的一个快速函数:
ReadFunky <- function(myFile) {
  fh <- gzfile(myFile)
  myFile <- readLines(fh)
  vecLen <- as.numeric(myFile[5])
  startAt <- grep(paste("^\\s+", vecLen), myFile)
  T1 <- lapply(startAt[-5], function(x) {
    scan(fh, n = vecLen, skip = x)
  })
  T2 <- gsub("\\(|\\)", "", 
             unlist(strsplit(myFile[(startAt[5]+1):length(myFile)], ")(", 
                             fixed = TRUE)))
  T2 <- read.csv(text = T2, header = FALSE)
  T2 <- split(T2, rep(1:vecLen, each = vecLen))
  T1[[5]] <- T2
  names(T1) <- myFile[startAt-1]
  T1
}

您可以将其应用于已下载的文件。只需使用实际路径替换您下载文件的位置。

temp <- ReadFunky("~/Downloads/AL182012_1030_0730.gz")

该函数返回一个列表。列表中的前四个项是坐标向量。
str(temp[1:4])
# List of 4
#  $ MERCATOR X COORDINATES ... KILOMETERS : num [1:159] -476 -470 -464 -458 -452 ...
#  $ MERCATOR Y COORDINATES ... KILOMETERS : num [1:159] -476 -470 -464 -458 -452 ...
#  $ EAST LONGITUDE COORDINATES ... DEGREES: num [1:159] -81.1 -81 -80.9 -80.9 -80.8 ...
#  $ NORTH LATITUDE COORDINATES ... DEGREES: num [1:159] 36.2 36.3 36.3 36.4 36.4 ...

第五项是一组包含来自您的“带括号的复杂数组”数据的2列data.frame。不确定这些数据的最佳结构是什么,所以我只是把它们放在了data.frame中。您将获得与给定数据集的预期值数量相同的data.frame(在本例中为159个)。
length(temp[[5]])
# [1] 159
str(temp[[5]][1:4])
# List of 4
# $ 1:'data.frame':  159 obs. of  2 variables:
#   ..$ V1: num [1:159] 7.59 7.6 7.59 7.59 7.58 ...
#   ..$ V2: num [1:159] -1.33 -1.28 -1.22 -1.16 -1.1 ...
# $ 2:'data.frame': 159 obs. of  2 variables:
#   ..$ V1: num [1:159] 7.66 7.66 7.65 7.65 7.64 ...
#   ..$ V2: num [1:159] -1.29 -1.24 -1.19 -1.13 -1.07 ...
# $ 3:'data.frame': 159 obs. of  2 variables:
#   ..$ V1: num [1:159] 7.73 7.72 7.72 7.71 7.7 ...
#   ..$ V2: num [1:159] -1.26 -1.21 -1.15 -1.1 -1.04 ...
# $ 4:'data.frame': 159 obs. of  2 variables:
#   ..$ V1: num [1:159] 7.8 7.8 7.79 7.78 7.76 ...
#   ..$ V2: num [1:159] -1.22 -1.17 -1.12 -1.06 -1.01 ...

更新

如果您想修改函数以便直接从FTP URL读取,将前两行更改为以下内容,并继续从“myFile”行:

ReadFunky <- function(myFile, fromURL = TRUE) {
  if (isTRUE(fromURL)) {
    x <- strsplit(myFile, "/")[[1]]
    y <- download.file(myFile, destfile = x[length(x)])
    fh <- gzfile(x[length(x)])
  } else {
    fh <- gzfile(myFile)
  }

使用方法如下:temp <- ReadFunky("ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/Operational/2012/AL182012/1023/1330/AL182012_1023_1330.gz"),对于您直接下载的文件;temp <- ReadFunky("~/AL182012_1023_1330.gz", fromURL=FALSE),对于您已在系统中保存的文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接