2014-03-25 30 views
0

我想读取一个ASCII TOMS网格格式的文件到R.我已经能够读取它以R打开的方式。但是,iy打开为线性矩阵。什么样的文件包含sumary可以在这里找到:读取ascii网格数据到矩阵格式

[Link](http://www.temis.nl/docs/README_TOMSASCII.pdf) 

数据集的样本可以在这里下载:

[Link](http://www.temis.nl/airpollution/no2col/no2monthscia.php?Year=2005&Month=04) 

的数据集是2006年1月,我只是给它改名为方便访问,因为有很多我需要合作。我在阅读它使用:

CCC<-read.csv("no2_200601.asc",header=FALSE,skip=4,sep="\t") 
dim(CCC) 
[1] 52560 1 

如何读取到R,使每个纬度的数据是在一个单一的行?我觉得这有助于建立一个适当的数据结构。 注意:让我试一试,简单地说它是我理解的:
这意味着结构是这样的:一行表示标题,例如lat = -89.9,接下来的144行有20个元素,每行属于行lat = -89.9;所以我现在的问题是在下一个“lat = ...”之前将所有这些元素读入一行。

此外,我只是通过一组文件,使用这种试图循环播放:

NO2files<-list.files(pattern=".asc", full.names=TRUE) 
f<-lapply(NO2files, function (x) readLines (x)) 

for (i in 1:length (NO2files)) { 
function(x) 
i<-readLines(x) 
pattern <- "[[:digit:]]+(?=\\sbins)" 
m <- regexpr(pattern, i[3], perl=TRUE) 
dim <- regmatches(i[3], m) 
m <- regexpr(pattern, i[4], perl=TRUE) 
dim[2] <- regmatches(i[4], m) 

dim <- as.integer(dim) 

pattern <- "(?<=undef=).*" 
m <- regexpr(pattern, i[2], perl=TRUE) 
na_string <- regmatches(i[2], m) 

dat1 <- i[-(1:4)] 
sep <- grepl("=", dat1, fixed=TRUE) 
dat2a <- dat1[sep] 
dat2b <- dat1[!sep] 
dat2b <- lapply(dat2b, substring, 
      first=seq(1,nchar(dat2b[1]),4), 
      last= seq(4,nchar(dat2b[1]),4)) 
dat2b <- unlist(dat2b) 
dat2b <- as.numeric(dat2b) 
dat2b[dat2b==as.numeric(na_string)] <- NA 
dat2b <- matrix(dat2b, nrow=dim[2], byrow=TRUE) 
dat2b <- dat2b[nrow(dat2b):1, ] 
} 
+0

这似乎不是一个很好的文件格式。我想知道为什么人们想出这样的事情。但是,我不知道任何可以解析这种格式的导入函数(这可能是一个包),因此您需要编写自己的解析器。 – Roland

+0

根本不好,根据我的理解,这意味着结构是这样的,一行代表标题,例如lat = -89.9,接下来的144行有20个元素,每行属于行lat = -89.9;所以我现在的问题是在下一个“lat = ...”之前将所有这些元素读入一行。 –

+0

本周晚些时候我可能会有一些时间来看看我是否可以尝试这些程序之一:http://disc.sci.gsfc.nasa.gov/ozone/additional/acdisc/additional/software-tools/:给你在R中使用之前预先处理您的数据的一种方式。不确定我现在正在构建一个包:-) – hrbrmstr

回答

0

几乎没有一样优雅的@Roland的例子,我不知道为什么有不同的值 - 实际上我对下面的评论(不同的文件)做了thx。

library(stringr) 
library(plyr) 
library(raster) 

f <- readLines("totno2_200601.asc") 

# how many lat/lon values 
bins.lon <- as.numeric(str_match(f[3], "Longitudes *: *([0-9]+) bins")[2]) 
bins.lat <- as.numeric(str_match(f[4], "Latitudes *: *([0-9]+) bins")[2]) 

# number of characters that represent a value 
num.width <- 4 

# how many lines do we need to encode the longitude bins 
bins.lon.lines <- as.integer(bins.lon/(80/num.width)) 

# where does the data start 
curr.lat.line <- 5 
curr.lat.bin <- 1 

m <- matrix(nrow=bins.lat, ncol=bins.lon+1) 

repeat { 

    # get current latitude 
    lat <- as.numeric(str_match(f[curr.lat.line], "lat=\ +([0-9\\.\\-]+)")[2]) 

    # show progress - not necessary 
    cat(curr.lat.bin, lat); cat("\n") 

    # get the values for the longitudes at current latitude 
    vals <- paste(f[(curr.lat.line+1):(curr.lat.line+bins.lon.lines)], sep="", collapse="") 

    # split them by 4 and assign to the proper entry 
    m[curr.lat.bin, ] <- c(lat, as.numeric(laply(seq(1, nchar(vals), 4), function(i) substr(vals, i, i+3)))) 

    curr.lat.bin <- curr.lat.bin + 1 
    curr.lat.line <- curr.lat.line + bins.lon.lines + 1 

    if (curr.lat.bin > bins.lat) { break } 

} 

m <- m[nrow(m):1, ] 

plot(raster(m)) 

plot

因为你增加了一个要求,这个能够在一个循环中被用来读取多个文件:如果你需要他们作为命名项

library(stringr) 
library(plyr) 
library(raster) 

# this is the function-ized version 

tomsToMatrix <- function(fname, verbose=FALSE) { 

    f <- readLines(fname) 

    bins.lon <- as.numeric(str_match(f[3], "Longitudes *: *([0-9]+) bins")[2]) 
    bins.lat <- as.numeric(str_match(f[4], "Latitudes *: *([0-9]+) bins")[2]) 

    num.width <- 4 
    bins.lon.lines <- as.integer(bins.lon/(80/num.width)) 
    curr.lat.line <- 5 
    curr.lat.bin <- 1 

    m <- matrix(nrow=bins.lat, ncol=bins.lon+1) 

    repeat { 
    lat <- as.numeric(str_match(f[curr.lat.line], "lat=\ +([0-9\\.\\-]+)")[2]) 
    if (verbose) { cat(curr.lat.bin, lat); cat("\n") } 
    vals <- paste(f[(curr.lat.line+1):(curr.lat.line+bins.lon.lines)], sep="", collapse="") 
    m[curr.lat.bin, ] <- c(lat, as.numeric(laply(seq(1, nchar(vals), 4), function(i) substr(vals, i, i+3)))) 
    curr.lat.bin <- curr.lat.bin + 1 
    curr.lat.line <- curr.lat.line + bins.lon.lines + 1 
    if (curr.lat.bin > bins.lat) { break } 
    } 

    m <- m[nrow(m):1, ] 

    return(m) 

} 

setwd("/data/toms") # whatever the source directory is for **your** files 

t.files <- list.files("/data/toms") 
t.files 
[1] "totno2_200504.asc" "totno2_200505.asc" "totno2_200506.asc" 

dat <- lapply(t.files, tomsToMatrix) 

str(dat) 
List of 3 
$ : num [1:720, 1:1441] 89.9 89.6 89.4 89.1 88.9 ... 
$ : num [1:720, 1:1441] 89.9 89.6 89.4 89.1 88.9 ... 
$ : num [1:720, 1:1441] 89.9 89.6 89.4 89.1 88.9 ... 

,应该不难添加。

+0

你没有相同的值,因为它不是相同的文件:) – alko989

+0

Doh!完全没有看Roland使用的文件名。 – hrbrmstr

+0

嗨hrbrmstr,我只是试图写这个循环,因为我必须为许多文件做这个。 NO2files <-list.files(pattern =“。asc”,full.names = TRUE) datalist = lapply(NO2files,function(y)readLines(y)) for(i in 1:length(datalist)){ ...... W <-matrix(nrow = bins.lat,ncol = bins.lon + 1) }。我得到一个错误错误:字符串必须是一个原子向量。如何使用“for”语句或lapply命令将其写入循环?当我用“矩阵(nrow = bins.lat,ncol = bins.lon + 1)”时,它说它是“非数字”。 –

1

这里是一个开始:

dat <- readLines("totno2_200504.asc") 

#parse dimensions 
pattern <- "[[:digit:]]+(?=\\sbins)" 
m <- regexpr(pattern, dat[3], perl=TRUE) 
dim <- regmatches(dat[3], m) 

m <- regexpr(pattern, dat[4], perl=TRUE) 
dim[2] <- regmatches(dat[4], m) 

dim <- as.integer(dim) 

#parse NA string 
pattern <- "(?<=undef=).*" 
m <- regexpr(pattern, dat[2], perl=TRUE) 
na_string <- regmatches(dat[2], m) 

#parse data 
dat1 <- dat[-(1:4)] 
sep <- grepl("=", dat1, fixed=TRUE) 
dat2a <- dat1[sep] #might be useful 
dat2b <- dat1[!sep] #the data 
dat2b <- lapply(dat2b, substring, 
       first=seq(1,nchar(dat2b[1]),4), 
       last= seq(4,nchar(dat2b[1]),4)) 
dat2b <- unlist(dat2b) 
dat2b <- as.numeric(dat2b) 
dat2b[dat2b==as.numeric(na_string)] <- NA 
dat2b <- matrix(dat2b, nrow=dim[2], byrow=TRUE) 
dat2b <- dat2b[nrow(dat2b):1, ] #flip in axis 

library(raster) 
plot(raster(dat2b)) 

enter image description here

+0

谢谢你们。两个答案似乎都合乎逻辑我去了第二个,因为我还不是很熟练的脚本编写技术。 –

+0

HI罗兰,我只是尝试循环这种提取方法,它给了我一个错误“矩阵(dat2b,nrow = dim [2],byrow = TRUE)中的错误: 无效'nrow'值(太大或NA)”我可能做错了什么? –

+0

由于我看不到您的代码,我不能说。可能的文件格式是不同的,用于查找维度的正则表达式不起作用?顺便说一句,如果你想在循环中使用它,你应该首先将它包装在一个函数中。 – Roland