Pertanyaan Baca file teks lebar tetap


Saya mencoba memuat kumpulan data yang diformat jelek ini ke dalam sesi R saya: 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

Sejauh ini, saya dapat membaca garis dengan

  x = readLines(path)

Tetapi file ini mencampur 'ruang putih' dengan '-' sebagai pemisah, dan saya bukan ahli regex. Saya menghargai bantuan untuk mengubahnya menjadi R-frame data yang bagus dan bersih. Terima kasih!


75
2018-01-17 16:33


asal


Jawaban:


Ini adalah file lebar tetap. Menggunakan read.fwf() membacanya:

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

Memperbarui

Paket readr (dirilis April, 2015) menyediakan alternatif yang sederhana dan cepat.

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

Perbandingan kecepatan: readr::read_fwf() ~ 2x lebih cepat dari utils::read.fwf ().


163
2018-01-17 16:45



Cara lain untuk menentukan lebar ...

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
)

The -1 dalam argumen lebar mengatakan ada kolom satu karakter yang harus diabaikan, -5 dalam argumen lebar mengatakan ada kolom lima karakter yang harus diabaikan, demikian juga ...

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


50
2018-06-12 21:42



Pertama, pertanyaan itu langsung dari kursus Coursera "Dapatkan Data dan Bersihkan" oleh Leeks. Meskipun ada bagian lain dari pertanyaan, bagian yang sulit adalah membaca file.

Yang mengatakan, kursus ini sebagian besar ditujukan untuk belajar.

Saya benci prosedur lebar tetap R. Ini lambat dan untuk sejumlah besar variabel, itu sangat cepat menjadi rasa sakit untuk meniadakan kolom tertentu, dll.

Saya pikir itu lebih mudah digunakan readLines() lalu dari penggunaan itu substr() untuk membuat variabel Anda

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
                     )

14
2017-10-17 18:35



Anda sekarang dapat menggunakan read_fwf() berfungsi di Hadley Wickham readr paket.

Peningkatan kinerja yang sangat besar dapat diharapkan, dibandingkan dengan basis read.fwf().


10
2018-04-10 10:20



Saya mendokumentasikan sini daftar alternatif untuk membaca file dengan lebar tetap di R, serta menyediakan beberapa tolok ukur yang paling cepat.

Pendekatan yang saya sukai adalah menggabungkan fread dengan stringi; itu kompetitif sebagai pendekatan tercepat, dan memiliki manfaat tambahan (IMO) untuk menyimpan data Anda sebagai 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

Perhatikan itu fread secara otomatis strip mengarah dan spasi spasi - kadang-kadang, ini tidak diinginkan, dalam hal ini ditetapkan strip.white = FALSE.


Kita juga bisa mulai dengan vektor lebar kolom ww dengan melakukan:

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)

Dan kita bisa memilih kolom mana yang dikecualikan lebih kuat dengan menggunakan indeks negatif seperti:

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

Lalu ganti col_ends$beg[ii] dengan abs(col_ends$beg[ii]) dan di baris berikutnya:

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

Terakhir, jika Anda ingin nama kolom dibaca secara programatik, Anda bisa membersihkannya 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 != ""]

(perhatikan bahwa menggabungkan langkah ini dengan fread akan membutuhkan membuat salinan tabel untuk menghapus baris header, dan dengan demikian akan tidak efisien untuk set data besar)


5
2018-03-31 14:34



Saya tidak tahu apa-apa tentang R, tetapi saya dapat memberi Anda regex yang akan cocok dengan baris seperti ini:

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

4
2018-01-17 16:43



Cara paling langsung adalah menggunakan read.fwf seperti yang ditunjukkan di atas.

Jika tujuan akhirnya adalah memasukkannya ke dalam R, Anda selalu dapat membacanya di Excel untuk memulai, gunakan fitur "text to cloumns" untuk memotong kolom secara visual, lalu simpan file akhir sebagai CSV. Setelah itu baca CSV ke R.


0
2017-12-09 05:15



Metode mudah jika untuk non-pemrogram (yang bersedia keluar dari R)

  1. Buka halaman di browser web.
  2. Salin dan tempelkan baris data ke editor teks. Hilangkan tajuk kolom.
  3. Gunakan pencarian-dan-ganti untuk mengubah banyak ruang dengan satu spasi (Ganti ruang-spasi dengan spasi. Terus klik sampai tidak ada dua kali lipat  ruang tersisa. Hanya membutuhkan beberapa detik).
  4. Gunakan pencarian-dan-ganti untuk mengganti tanda hubung (-) dengan spasi
  5. ForUse search-and-replace untuk mengganti ruang dengan koma-space.

Anda sekarang memiliki file .csv yang juga mudah dibaca oleh manusia; Simpan itu. Muat itu ke Excel, R, atau apa pun, dan terus diproses.


0
2017-07-17 03:06