2

如何读取如下示例中的数据?(我的实际文件类似于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()打开不允许对数据进行seek操作,所以scan()s全部倒带并从文件的开头开始。如果我解压缩文件并对未压缩的数据进行操作,我可以使用 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.
4

1 回答 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")

该函数返回一个list. 列表中的前四项是坐标向量。

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-column data.frame,其中包含“带括号的复杂数组”中的数据。不太确定这个数据的最佳结构是什么,所以我只是把它放在data.frames. 您将获得data.frame与给定数据集的预期值一样多的 s(在本例中为 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)的文件,以及对于您已经保存在系统上的文件。

于 2013-07-07T17:15:13.910 回答