2013-01-17 49 views
71

我試圖加載這個醜陋的格式的數據集到我的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) 

但文件混合'空白'和' - '作爲分隔符,我不是正則表達式專家。 我感謝任何幫助把它變成一個漂亮和乾淨的R數據框架。 謝謝!

+5

而看看'read.fwf'閱讀閱讀修復ed寬度格式化數據。 –

+0

我認爲處理每一行是一個更好的主意。它將' - '和''字符混合在一起。 – Fernando

+0

或者,您可以說空格或 - 只是一個字符,因此首先用製表符替換所有多次出現的空格,然後拆分所有制表符分隔的條目 - 或空格。 – GitaarLAB

回答

157

這是一個固定寬度的文件。使用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 

更新

readr(4月發行,2015年)提供了一個簡單,快捷的選擇。

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()是〜2倍比utils::read.fwf()更快。

+7

@Andrie你怎麼知道寬度和跳躍是多少? – Koba

+11

@Koba:我將其中一行復制並粘貼到具有列數的文本編輯器中,並手動計算每列的寬度(包括需要時的空白)。你也可以告訴你,在你得到原始數據之前,你需要跳過4整行。 – rayryeng

+5

@ Pavithra的回答如下,用於跳過不需要的空白的負列寬可能更適合接受的答案。 –

4

我不知道一個關於R的事情,但我可以爲您提供一個正則表達式將匹配這樣的臺詞:

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

另一種確定的寬度......

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 
) 

-1的寬度論點說,有是應該忽略一個字符列,在-5寬度論點說,有一個五個字符列應被忽略,同樣...

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

14

首先,這個問題是直接從一個韭菜的Coursera「獲取數據並進行清潔」等課程。雖然還有另一部分問題,但困難的部分是閱讀文件。

也就是說,課程主要是爲了學習。

我討厭R的固定寬度程序。它是緩慢和大量的變量,它很快成爲否定某些列的疼痛等

我覺得它更容易使用readLines(),然後從使用substr()讓你的變量

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 
        ) 
+0

這種方法適用於我。另外兩個提示:1)您可以將mydata定義爲只有您需要的數據。因此,如果您只需要第四列數據,它可以像mydata < - data.frame(var4 = substr(x,29,32))一樣簡單。另外,對於Windows用戶,Notepad ++和TextFX插件將爲您提供一個簡單明瞭的統計字符標尺,以便您可以計算出在substr中啓動和停止的值。但請注意,停止值比您要保留的最後一個字符的位置多一個。 – globalSchmidt

0

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

那麼如果最終目標是將它放入R中,您可以隨時將其讀入Excel中,以便使用「text to cloumns」功能以可視化方式剪切列,然後將最終文件保存爲CSV 。之後,將CSV讀入R.

0

一個簡單的方法,如果非程序員(誰願意的R之外去)

  1. 打開頁面的Web瀏覽器。
  2. 將數據行復制並粘貼到文本編輯器中。忽略列標題。
  3. 使用搜索和替換來改變單個空間的多個空間 (用空格替換空間,繼續點擊,直到沒有雙重空間 ,只需幾秒鐘)。
  4. 使用搜索替換用空格替換破折號( - )
  5. ForUse搜索替換用逗號空格替換空格。

您現在有一個.csv文件,對於人來說也很容易閱讀;保存。 將其加載到Excel,R或其他內容中,並繼續處理。

5

本文檔here用於讀取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

另請注意我選擇了sep = "\n"以防止任何內線分裂。如果this issue已實施,我們將擁有更強大的替代方案。


我們也已經做開始與列寬ww的載體:

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)) 

然後將col_ends$beg[ii]替換爲abs(col_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需要,以消除標題行創建表的副本,從而將是低效的大型數據集)

相關問題