读取固定宽度的文本文件

我试图把这个丑陋格式的数据集加载到我的R会话中: http : //www.cpc.ncep.noaa.gov/data/indices/wksst8110.for

Weekly SST data starts week centered on 3Jan1990 Nino1+2 Nino3 Nino34 Nino4 Week SST SSTA SST SSTA SST SSTA SST SSTA 03JAN1990 23.4-0.4 25.1-0.3 26.6 0.0 28.6 0.3 10JAN1990 23.4-0.8 25.2-0.3 26.6 0.1 28.6 0.3 17JAN1990 24.2-0.3 25.3-0.3 26.5-0.1 28.6 0.3 

到目前为止,我可以阅读

  x = readLines(path) 

但该文件混合“空白”和“ – ”作为分隔符,我不是一个正则expression式专家。 我欣赏任何帮助把它变成一个漂亮和干净的R数据框架。 谢谢!

这是一个固定宽度的文件。 使用read.fwf()来读取它:

 x <- read.fwf( file=url("http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for"), skip=4, widths=c(12, 7, 4, 9, 4, 9, 4, 9, 4)) head(x) V1 V2 V3 V4 V5 V6 V7 V8 V9 1 03JAN1990 23.4 -0.4 25.1 -0.3 26.6 0.0 28.6 0.3 2 10JAN1990 23.4 -0.8 25.2 -0.3 26.6 0.1 28.6 0.3 3 17JAN1990 24.2 -0.3 25.3 -0.3 26.5 -0.1 28.6 0.3 4 24JAN1990 24.4 -0.5 25.5 -0.4 26.5 -0.1 28.4 0.2 5 31JAN1990 25.1 -0.2 25.8 -0.2 26.7 0.1 28.4 0.2 6 07FEB1990 25.8 0.2 26.1 -0.1 26.8 0.1 28.4 0.3 

更新

package readr (2015年4月发布)提供了一个简单而快速的select。

 library(readr) x <- read_fwf( file="http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for", skip=4, fwf_widths(c(12, 7, 4, 9, 4, 9, 4, 9, 4))) 

速度比较: readr::read_fwf()utils::read.fwf ()快了2倍。

另一种确定宽度的方法

 df <- read.fwf( file=url("http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for"), widths=c(-1,9,-5,4,4,-5,4,4,-5,4,4,-5,4,4), skip=4 ) 

widths参数中的-1表示应该忽略一个字符的列,widths参数中的-5表示有一个应忽略的五个字符的列,同样…

ref: https : //www.inkling.com/read/r-cookbook-paul-teetor-1st/chapter-4/recipe-4-6

首先,这个问题直接来自于韭菜的Coursera“获取数据和清理它”课程。 虽然还有另外一部分问题,但最难的部分是阅读文件。

也就是说,课程主要是为了学习。

我讨厌R的固定宽度的程序。 这是缓慢的和大量的variables,它很快就成为否定某些列等的痛苦。

我认为它更容易使用readLines ,然后从那里使用substr来使你的variables

 x <- readLines(con=url("http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for")) # Skip 4 lines x <- x[-(1:4)] mydata <- data.frame(var1 = substr(x,1,10), var2 = substr(x, 16,19), var3 = substr(x, 20, 23), var4 = substr(x, 29, 32) # and so on and so on ) 

现在可以在Hadley Wickham的readr包中使用read_fwf()函数。

  • 公告: http : //blog.rstudio.org/2015/04/09/readr-0-1-0/
  • 开发页面: https : //github.com/hadley/readr
  • CRAN页面: http : //cran.r-project.org/web/packages/readr/index.html

与基本的read.fwf()相比,性能有了巨大的提高。

我不知道关于R的一些东西,但是我可以给你一个正则expression式来匹配这样的行:

 \s[0-9]{2}[AZ]{3}[0-9]{4}(\s{5}[0-9]+\.[0-9]+[ -][0-9]+\.[0-9]+){4} 

我很抱歉这么久,我会尽量优化它。

编辑:
哈,现在它适合一条线。

我在这里列出了用于读取R中固定宽度文件的替代方法列表,并提供了一些速度最快的基准。

我喜欢的方法是把freadstringi结合起来。 它作为最快的方法具有竞争力,并且具有将数据存储为data.table的额外好处(IMO):

 library(data.table) library(stringi) col_ends <- list(beg = c(1, 10, 15, 19, 23, 28, 32, 36, 41, 45, 49, 54, 58), end = c(9, 14, 18, 22, 27, 31, 35, 40, 44, 48, 53, 57, 61)) data = fread( "http://www.cpc.ncep.noaa.gov/data/indices/wksst8110.for", header = FALSE, skip = 4L, sep = "\n" )[, lapply(1:(length(col_ends$beg)), function(ii) stri_sub(V1, col_ends$beg[ii], col_ends$end[ii])) ][ , paste0("V", c(2, 5, 8, 11)) := NULL] # V1 V3 V4 V6 V7 V9 V10 V12 V13 # 1: 03JAN1990 23.4 -0.4 25.1 -0.3 26.6 0.0 28.6 0.3 # 2: 10JAN1990 23.4 -0.8 25.2 -0.3 26.6 0.1 28.6 0.3 # 3: 17JAN1990 24.2 -0.3 25.3 -0.3 26.5 -0.1 28.6 0.3 # 4: 24JAN1990 24.4 -0.5 25.5 -0.4 26.5 -0.1 28.4 0.2 # 5: 31JAN1990 25.1 -0.2 25.8 -0.2 26.7 0.1 28.4 0.2 # --- # 1365: 24FEB2016 27.1 0.9 28.4 1.8 29.0 2.1 29.5 1.4 # 1366: 02MAR2016 27.3 1.0 28.6 1.8 28.9 1.9 29.5 1.4 # 1367: 09MAR2016 27.7 1.2 28.6 1.6 28.9 1.8 29.6 1.5 # 1368: 16MAR2016 27.5 1.0 28.8 1.7 28.9 1.7 29.6 1.4 # 1369: 23MAR2016 27.2 0.9 28.6 1.4 28.8 1.5 29.5 1.2 

请注意, fread自动strip.white = FALSE前导空白和尾随空白 – 有时候,这是不可取的,在这种情况下,设置strip.white = FALSE

另外请注意,我select了sep = "\n"来防止任何内线分裂。 如果这个问题得到执行,我们将有一个更强大的select。


我们也可以通过做一个列宽度向量来开始:

 ww <- c(9, 5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 4) nd <- cumsum(ww) col_ends <- list(beg = c(1, nd[-length(nd)]+1L), end = nd) 

而且我们可以通过使用负指数来挑选哪些列更强健地排除:

 col_ends <- list(beg = c(1, -10, 15, 19, -23, 28, 32, -36, 41, 45, -49, 54, 58), end = c(9, 14, 18, 22, 27, 31, 35, 40, 44, 48, 53, 57, 61)) 

然后用abs(col_ends$beg[ii])replacecol_ends$beg[ii] ,并在下一行:

 paste0("V", which(col_ends$beg < 0)) 

最后,如果您希望以编程方式读取列名,则可以使用readLines清理:

 cols <- gsub("\\s", "", sapply(1:(length(col_ends$beg)), function(ii) stri_sub(readLines(URL, n = 4L)[4L], col_ends$beg[ii]+1L, col_ends$end[ii]+1L))) cols <- cols[cols != ""] 

(注意,将这一步与fread结合起来需要创build一个表的副本,以便删除标题行,因此对于大型数据集来说是低效的)

对于非程序员(谁愿意出去R)

  1. 在网页浏览器中打开页面。
  2. 将数据行复制并粘贴到文本编辑器中。 省略列标题。
  3. 使用search和replacefunction可以用一个空格来改变多个空格(用空格replace空格,继续点击,直到没有剩余空格为止,只需要几秒钟)。
  4. 使用search和replacereplace短划线( – )与空格
  5. ForUsesearch和replace用逗号空间replace空格。

你现在有一个.csv文件,对于人来说也很容易阅读; 保存。 加载到Excel,R,或其他任何,并继续处理。

最直接的方法是使用上面指出的read.fwf。

那么如果最终目标是把它放到R中,你可以随时把它读入Excel中,使用“text to cloumns”function以可视化的方式剪切出列,然后将最终的文件保存为CSV。 之后,将CSV读入R.