Sabit genişlikli metin dosyasını oku


93

Bu çirkin biçimlendirilmiş veri kümesini R oturumuma yüklemeye çalışıyorum: 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

Şimdiye kadar satırları okuyabilirim

  x = readLines(path)

Ancak dosya ayırıcı olarak "beyaz boşluk" ile "-" arasında bir karışım içeriyor ve ben bir normal ifade uzmanı değilim. Bunu güzel ve temiz bir R veri çerçevesine dönüştürmek için her türlü yardıma minnettarım. Teşekkürler!


5
read.fwfSabit genişlikte biçimlendirilmiş verileri okumak için bir göz atın .
Paul Hiemstra

1
Her satırı işlemenin daha iyi bir fikir olduğunu düşünüyorum. '-' ile '' karakterlerini karıştırır.
Fernando

Alternatif olarak, beyaz boşluk veya - sadece bir karakter diyebilirsiniz, bu nedenle önce bir boşluğun tüm çoklu oluşumlarını bir sekme karakteriyle değiştirin, ardından sekmeyle ayrılmış tüm girişlerin açık - veya beyaz boşluğunu bölün.
GitaarLAB

Sabit genişlik = ayırıcı yok. Bu, "-" işaretinin bir eksi işareti olduğu ve boşlukların da ayırıcı olmadığı anlamına gelir, yalnızca sayı mevcut genişliğin tamamını doldurmadığında ortaya
çıkarlar

Yanıtlar:


184

Bu sabit genişlikte bir dosyadır. read.fwf()Okumak için kullanın :

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

Güncelleme

Paket readr(Nisan 2015'te yayınlandı) basit ve hızlı bir alternatif sunuyor.

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

Hız karşılaştırması: readr::read_fwf()~ 2 kat daha hızlıydı utils::read.fwf ().


10
@Andrie genişliklerin ve atlamaların ne olduğunu nasıl bildin?
Koba

12
@Koba: Satırlardan birini kopyalayıp sütun sayısı olan bir metin düzenleyicisine yapıştırdım ve her sütun için genişlikleri manuel olarak saydım (gerektiğinde boşluk dahil). Ayrıca ham verilere ulaşmadan önce 4 tam satırı atlamanız gerektiğini de söyleyebilirsiniz.
rayryeng

5
@ Pavithra'nın istenmeyen boşlukları atlamak için negatif sütun genişlikleri içeren aşağıdaki cevabı, kabul edilen cevap için daha uygun olabilir.
Marius Butuc

1
@Andrie fwf_widths değerlerini nasıl aldınız?
BICube

3
@Ala inanıyorum readr::fwf_emptyki sizin için genişlikleri tahmin etmeye çalışacağız Örnekler için readr::read_fwfkullanımı gösterir readr::fwf_empty.
Jake Fisher

55

Genişlikleri belirlemenin başka bir yolu ...

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
)

Genişlikler bağımsız değişkenindeki -1, göz ardı edilmesi gereken tek karakterlik bir sütun olduğunu, genişlikler bağımsız değişkenindeki -5 ise göz ardı edilmesi gereken beş karakterlik bir sütun olduğunu söylüyor, aynı şekilde ...

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


20

Öncelikle, bu soru doğrudan Pırasa tarafından hazırlanan Coursera "Verileri Al ve Temizle" kursundan geliyor. Sorunun bir başka kısmı varken, zor olan kısmı dosyayı okumaktır.

Bununla birlikte, kurs çoğunlukla öğrenmeye yöneliktir.

R'nin sabit genişlik prosedüründen nefret ediyorum. Yavaştır ve çok sayıda değişken için, belirli sütunları vb. Reddetmek çok hızlı bir acı haline gelir.

Bence kullanması daha kolay readLines()ve bundan sonra substr()değişkenlerinizi oluşturmak için

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
                     )

2
Bu yaklaşım benim için çalıştı. İki ek ipucu: 1) verilerimi yalnızca ihtiyacınız olan veriler olarak tanımlayabilirsiniz. Dolayısıyla, mydata <- data.frame(var4 = substr(x,29,32))yalnızca dördüncü veri sütununa ihtiyacınız varmış gibi basit olabilir . Ayrıca, Windows kullanıcıları için, TextFX eklentisine sahip Notepad ++ size basit ve basit, sayılan bir karakter cetveli sağlar, böylece başlangıç ​​ve bitiş değerlerini içine ne koyacağınızı anlayabilirsiniz substr. Bununla birlikte, durma değerinin, korumak istediğiniz son karakterin konumundan bir fazla olduğunu unutmayın.
globalSchmidt


5

Ben belge burada R sabit genişlikli dosyaları okuma, hem de en hızlı olduğu için bazı kriterler sağlamak için alternatifler listesi.

Benim tercih yaklaşım birleştirmektir freadile stringi; en hızlı yaklaşım olarak rekabetçidir ve verilerinizi şu şekilde depolamanın ek faydasına (IMO) sahiptir data.table:

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 = NULL
  )[, 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

Not freadbu durumda kümesinde, bazen, bu istenmeyen bir durumdur - otomatik olarak ön ve boşluk arka şeritler strip.white = FALSE.


Şunları wwyaparak da sütun genişlikleri vektörüyle başlayabilirdik :

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)

Aşağıdakiler gibi negatif endeksler kullanarak hangi sütunları daha sağlam bir şekilde hariç tutacağımızı seçebilirdik:

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

Ardından sonraki satırda ve col_ends$beg[ii]ile değiştirin abs(col_ends$beg[ii]):

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

Son olarak, sütun adlarının da programlı olarak okunmasını istiyorsanız, şunları temizleyebilirsiniz 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 != ""]

(Bu adımı birleştirmenin fread, başlık satırını kaldırmak için tablonun bir kopyasını oluşturmayı gerektireceğini ve bu nedenle büyük veri kümeleri için verimsiz olacağını unutmayın)


4

R hakkında hiçbir şey bilmiyorum, ancak size bu tür satırlarla eşleşen bir normal ifade sağlayabilirim:

\s[0-9]{2}[A-Z]{3}[0-9]{4}(\s{5}[0-9]+\.[0-9]+[ -][0-9]+\.[0-9]+){4}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.