고정 너비 텍스트 파일 읽기


90

이 추악한 형식의 데이터 세트를 내 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고정 너비 형식의 데이터를 읽으려면 살펴보십시오 .
Paul Hiemstra

1
각 행을 처리하는 것이 더 좋은 생각이라고 생각합니다. '-'와 ''문자를 혼합합니다.
Fernando

또는 공백 또는-는 하나의 문자 일 수 있으므로 먼저 여러 공백을 탭 문자로 바꾼 다음 모든 탭으로 구분 된 항목을-또는 공백으로 분할합니다.
GitaarLAB

고정 너비 = 구분 기호 없음. 의미하는 "-"마이너스 기호이고 공간이 수가 가능한 전체 폭 기입하지 않는 경우에 그들은 단지 발생, 분리하거나하지 않습니다
에우제비오 Rufian-Zilbermann

답변:


183

이것은 고정 너비 파일입니다. 사용 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(2015 년 4 월 출시)는 간단하고 빠른 대안을 제공합니다.

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


8
@Andrie 폭과 스킵이 무엇인지 어떻게 알았습니까?
Koba 2014

12
@Koba : 열 개수가있는 텍스트 편집기에 줄 중 하나를 복사하여 붙여넣고 각 열의 너비를 수동으로 계산했습니다 (필요한 경우 공백 포함). 또한 원시 데이터에 도달하기 전에 4 줄 전체를 건너 뛰어야한다고 말할 수 있습니다.
rayryeng 2014

5
원하지 않는 공백을 건너 뛰기위한 음수 열 너비가있는 아래 @Pavithra의 대답은 허용되는 대답에 더 적합 할 수 있습니다.
Marius Butuc 2014

1
@Andrie fwf_widths 값을 어떻게 얻었습니까?
BICube 2017

3
@Ala 나는 readr::fwf_empty당신을 위해 너비를 추측하려고 시도 할 것이라고 믿습니다 . 의 예제 readr::read_fwfreadr::fwf_empty.
제이크 피셔

55

너비를 결정하는 또 다른 방법 ...

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는 마찬가지로 무시해야하는 5 자 열이 있음을 나타냅니다.

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


20

먼저이 질문은 Leeks의 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
                     )

2
이 접근 방식은 저에게 효과적이었습니다. 두 가지 추가 팁 : 1) mydata를 필요한 데이터로만 정의 할 수 있습니다. 따라서 mydata <- data.frame(var4 = substr(x,29,32))네 번째 데이터 열만 필요한 것처럼 간단 할 수 있습니다 . 또한 Windows 사용자의 경우 TextFX 플러그인이 포함 된 Notepad ++를 사용하면 단순하고 단순하며 계산 된 문자 눈금자를 얻을 수 있으므로에 시작 및 중지 값을 입력 할 내용을 파악할 수 있습니다 substr. 그러나 중지 값은 보존하려는 마지막 문자의 위치보다 하나 더 많습니다.
globalSchmidt


5

여기 에 R에서 고정 너비 파일을 읽기위한 대안 목록을 문서화 하고 가장 빠른 벤치 마크를 제공합니다.

내가 선호하는 접근 방식은 다음과 결합하는 것 fread입니다 stringi. 가장 빠른 접근 방식으로 경쟁력이 있으며 데이터를 다음과 같이 저장하는 추가 이점 (IMO)이 있습니다 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

fread선행 및 후행 공백 을 자동으로 제거합니다. 때로는 바람직하지 않은 경우도 strip.white = FALSE있습니다.


다음 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하면 헤더 행을 제거하기 위해 테이블 ​​사본을 만들어야하므로 대용량 데이터 세트의 경우 비효율적입니다.)


4

R에 대해 잘 모르겠지만 다음과 같은 행과 일치하는 정규식을 제공 할 수 있습니다.

\s[0-9]{2}[A-Z]{3}[0-9]{4}(\s{5}[0-9]+\.[0-9]+[ -][0-9]+\.[0-9]+){4}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.