Saya mencoba memuat kumpulan data berformat jelek ini ke 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 bisa membaca baris dengan
x = readLines(path)
Tetapi file tersebut mencampur 'ruang putih' dengan '-' sebagai pemisah, dan saya bukan ahli regex. Saya menghargai bantuan apa pun untuk mengubahnya menjadi bingkai data R yang bagus dan bersih. Terima kasih!
r
fixed-width
Fernando
sumber
sumber
read.fwf
untuk membaca data berformat lebar tetap.Jawaban:
Ini adalah file dengan lebar tetap. Gunakan
read.fwf()
untuk 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) memberikan 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 dariutils::read.fwf ()
.sumber
readr::fwf_empty
akan mencoba menebak lebarnya untuk Anda. Contoh untukreadr::read_fwf
menunjukkan penggunaan untukreadr::fwf_empty
.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 )
-1 dalam argumen widths mengatakan ada kolom satu karakter yang harus diabaikan, argumen -5 di widths 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
sumber
Pertama, pertanyaan itu langsung dari kursus Coursera "Dapatkan Data dan Bersihkan" oleh Leeks. Meskipun ada bagian lain dari pertanyaan itu, bagian tersulitnya adalah membaca file.
Konon, kursus tersebut sebagian besar ditujukan untuk pembelajaran.
Saya benci prosedur lebar tetap R. Ini lambat dan untuk sejumlah besar variabel, sangat cepat menjadi merepotkan untuk meniadakan kolom tertentu, dll.
Saya pikir lebih mudah digunakan
readLines()
dan kemudian dari penggunaan itusubstr()
untuk membuat variabel Andax <- 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 )
sumber
mydata <- data.frame(var4 = substr(x,29,32))
jika Anda hanya membutuhkan data kolom keempat. Selain itu, untuk pengguna Windows, Notepad ++ dengan plugin TextFX akan memberi Anda penggaris karakter yang dihitung dan sederhana sehingga Anda dapat mengetahui apa yang harus dimasukkan ke dalam nilai awal dan penghentiansubstr
. Perhatikan, bagaimanapun, bahwa nilai stop lebih dari satu posisi dari karakter terakhir yang ingin Anda pertahankan.Sekarang Anda dapat menggunakan
read_fwf()
fungsi tersebut dalamreadr
paket Hadley Wickham .Peningkatan kinerja yang sangat besar diharapkan, dibandingkan dengan basis
read.fwf()
.sumber
Saya mendokumentasikan di sini daftar alternatif untuk membaca file dengan lebar tetap di R, serta menyediakan beberapa tolok ukur yang tercepat.
Pendekatan pilihan saya adalah menggabungkan
fread
denganstringi
; itu kompetitif sebagai pendekatan tercepat, dan memiliki manfaat tambahan (IMO) menyimpan data Anda sebagaidata.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 bahwa
fread
secara otomatis menghapus spasi kosong di depan dan di belakang - terkadang, ini tidak diinginkan, dalam hal ini ditetapkanstrip.white = FALSE
.Kita juga bisa memulai 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 akan 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))
Kemudian ganti
col_ends$beg[ii]
denganabs(col_ends$beg[ii])
dan di baris berikutnya:paste0("V", which(col_ends$beg < 0))
Terakhir, jika Anda ingin nama kolom juga dibaca secara terprogram, Anda dapat membersihkannya dengan
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 memerlukan pembuatan salinan tabel untuk menghapus baris header, dan karenanya tidak efisien untuk kumpulan data yang besar)sumber
Saya tidak tahu apa-apa tentang R, tetapi saya dapat memberi Anda regex yang akan cocok dengan baris seperti itu:
\s[0-9]{2}[A-Z]{3}[0-9]{4}(\s{5}[0-9]+\.[0-9]+[ -][0-9]+\.[0-9]+){4}
sumber