1.2 데이터 불러오기

먼저 데이터 불러오기와 관련한 제 함수들과 이들의 사용방법에 대하여 살펴보기로 한다. readr 패키지에는 데이터 파일의 종류에 따라 사용할 수 있는 read_* 접두사로 시작하는 다양한 함수들이 있다.

다음은 그림 1.1readr 패키지에 테이블 데이터를 읽어오는 치트 시트의 일부이다.

`readr` 패키지의 테이블 데이터 불러오기 함수들

Figure 1.1: readr 패키지의 테이블 데이터 불러오기 함수들

1.2.1 관련 함수

readr 패키지의 함수 대부분은 플랫 파일데이터 프레임(엄밀히 말하면 tibble)으로 바꾸는 역학을 하는 함수들이다.

참고로 불러올 데이터는 보통 우리가 ’표(Table)’라고 하는 형태의 데이터가 *.txt, *.csv, *.xlsx 등의 형태로 저장되어 있는 것을 전제로 한다. 이러한 데이터 파일에 저장된 데이터의 형태를 고려하여 적절한 함수를 사용해야 하는 것이다. 우리가 사용할 수 있는 대표적인 함수들은 다음과 같다.

  • read_csv() : 쉼표(,)로 데이터 항목들이 분리된 파일
  • read_tsv() : 탭(\t)으로 데이터 항목들이 분리된 파일
  • read_delim() : 임의의 구분자(delimeter)로 데이터 항목들이 분리된 파일
  • read_fwf() : 고정된 너비로 데이터 항목들이 분리된 파일. 단, 이 때는 각 필드(항목)의 너비 또는 위치 지정이 필요.
    • 필드 너비 : fwf_widths() 함수 이용
    • 필드 위치 : fwf_positions() 함수 이용
  • read_table() : 고정 너비 파일의 일반적 변형 형태인 데이터 항목들이 공백으로 분리된 파일
  • read_log() : Apache 스타일의 로그 파일 (read_log() 기반으로 구축되어 더 많은 유용한 도구를 제공하는 webreadr도 있음)

이러한 함수들의 특징으로 이 함수들을 이용하는 문법(syntax)이 거의 비숫하다는 것이다. 하나 함수 사용방법을 익히면 나머지도 쉽게 사용할 수 있다는 것이다.

따라서 이 절에서는 대부분 read_csv()에 초점을 맞추어 살펴볼 것이다. 그 이유는 *.csv 파일은 가장 일반적인 형태의 데이터 저장 형태일 뿐 만 아니라, read_csv() 를 이해하면 readr 의 다른 함수들도 쉽게 사용할 수 있기 때문이다.

1.2.2 파일 경로 지정

read_*() 함수의 첫 번째 인수가 가장 중요한 인수이다. 이 인수는 불러올 파일의 경로를 지정하면, read_*() 함수가 그 데이터를 불러오게 되는 것이다.

예를 들어, 현재의 작업 디렉토리 아래에 있는 data1 폴더에 heights.csv 파일이 있다고 할 때, read_csv() 함수사용할 수 있고, 이때 첫 번쨰 인수는 data1/heights.csv가 되는 것이다. (이떄 폴더와 파일 이름 사이의 /는 ’\\’로 사용해도 된다.)

heights <- read_csv("data1/heights.csv")
## 
## -- Column specification --------------------------------------------------------
## cols(
##   earn = col_double(),
##   height = col_double(),
##   sex = col_character(),
##   ed = col_double(),
##   age = col_double(),
##   race = col_character()
## )
heights
## # A tibble: 1,192 x 6
##     earn height sex       ed   age race    
##    <dbl>  <dbl> <chr>  <dbl> <dbl> <chr>   
##  1 50000   74.4 male      16    45 white   
##  2 60000   65.5 female    16    58 white   
##  3 30000   63.6 female    16    29 white   
##  4 50000   63.1 female    16    91 other   
##  5 51000   63.4 female    17    39 white   
##  6  9000   64.4 female    15    26 white   
##  7 29000   61.7 female    12    49 white   
##  8 32000   72.7 male      17    46 white   
##  9  2000   72.0 male      15    21 hispanic
## 10 27000   72.2 male      12    26 white   
## # ... with 1,182 more rows
  • read_csv()를 실행하면 각 열의 이름데이터 유형을 제공하는 ‘col_types, cols’이 화면 출력된다. 이는 readr 패키지에서 중요한 부분이다. 파일 파싱하기에서 다시 살펴보겠다.

참고로, 인라인(in-line) CSV 파일이 첫 번째 인수가 될 수도 있다. 이것은 readr 패키지로 데이터 불러오기를 시험해 볼 때 그리고 다른 사람들과 공유할 수 있는 재현가능한 예제를 만들 때 유용하게 사용할 수 있다.

아래의 설명에서는 이러한 인라인 csv 파일을 이용한다. 예를 들어, 다음의 스크립트를 실행에 본다.

read_csv("a, b, c
          1, 2, 3
          4, 5, 6")
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     6
  • 위의 스크립트는 a, b, c 등의 3개의 열(column)과 2 개의 행(row)으로 구성되는 테이블 데이터를 tibble 클래스로 불러들인다.

1.2.3 다른 인수들

첫 번째 인수 이외에도 부가적인 다양한 인수들이 있다.

1.2.3.1 skip = 인수와 comment = 인수

skipcomment 등의 두 인수들은 기본적으로 데이터 파일에 메타 데이터가 있는 경우 이를 지정하는데 사용되는 인수이다. 이 두 인수 모두 read_csv() 함수가 데이터 파일의 첫 번째 줄을 “열 이름”으로 사용하고 있다. 이는 매우 일반적인 규칙으로 적용된다.

그런데 이 부분을 조정해야 하는 두 가지의 경우가 있다.

첫째, 파일 앞 부분에 ** 메타 데이터가 한 줄이 아니고 여러 줄이 있는 경우**이다. 이 때, skip = n 을 사용하여 처음의 n개의 데이터 줄을 건너 뛸 수 있다. 또는 comment = "#" 을 사용하여 # 으로 시작하는 모든 줄을 무시하게 할 수 있다.

skip 인수의 사용 예를 들어본다.

read_csv("메타 데이터 첫번째 행
          메타 데이터 두번째 행
          x, y, z
          1, 2, 3", 
          skip = 2)
## # A tibble: 1 x 3
##       x     y     z
##   <dbl> <dbl> <dbl>
## 1     1     2     3
  • 첫 번째 인수는 (데이터가 ,로 구분된) 인라인 csv 형식이다.
  • skip = 2로 인해 첫 두 줄은 데이터로 읽혀지지 않음을 알 수 있다.

마찬가지로 comment 인수의 사용예는 다음과 같다.

read_csv("# 건너뛰고 싶은 주석
          x, y, z
          1, 2, 3", 
          comment = "#")
## # A tibble: 1 x 3
##       x     y     z
##   <dbl> <dbl> <dbl>
## 1     1     2     3
  • 첫번째 인수는 ‘인라인 csv’ 파일이다.
  • 두번째 인수인 comment = “#”로 인해, # 시작하는 첫째 줄의 내용이 데이터로 읽혀지지 않음을 알 수 있다.

1.2.3.2 col_names = 인수

col_names = 인수는 데이터 파일의 첫 줄을 컬럼 제목으로 사용할 지를 지정하게 된다. 이는 데이터 파일의 첫째 줄에 열 이름이 없는 경우가 있을 수 있다.

이 때. 다음의 예와 같이 col_names = FALSE를 사용하면 read_csv()가 첫 행을 헤드로 취급하지 않고 모두 데이터로 읽어 들이게 된다. 이때, 컬럼의 제목은 X1에서 Xn(n은 컬럼의 갯수)까지 순차적으로 자동으로 부여 된다.

read_csv("1, 2, 3\n4, 5, 6", col_names = FALSE)
## # A tibble: 2 x 3
##      X1    X2    X3
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     6
  • 컬럼 제목이 지정되어 있지 않게 때문에 컬럼의 제목이 X1, X2, X3 등으로 자동 설정되었다.
  • 인라인 csv 파일 안에 있는 "\n"새 줄을 추가하는 편리한 단축키이다.

한편, col_names =에 인수 값 즉 컬럼의 제목을 다음과 같이 지정해 줄 수도 있다. 즉, col_names열 이름으로 사용할 문자형 벡터를 지정할 수 있다.

read_csv("1, 2, 3\n4, 5, 6", col_names = c("x", "y", "z"))
## # A tibble: 2 x 3
##       x     y     z
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     6
  • 이 때, 컬럼 제목을 c(“x,” “y,” “z”)로 지정하였기 때문에 컬럼 제목이 x, y, z로 되어 있다. 다.

1.2.3.3 na = 인수

일반적으로 불러들인 데이터에 대한 조정이 필요한 또 다른 옵션은 na 이다. 이 인수에 값을 지정하여 데이터 파일에서 결측값(missing value)을 나타내는데 사용되는 값(들)을 지정할 수 있다.

read_csv("a, b, c\n1, 2, .", na = ".")
## # A tibble: 1 x 3
##       a     b c    
##   <dbl> <dbl> <lgl>
## 1     1     2 NA
  • 두번째 줄의 데이터 중 . 부분은 na = "." 인수에 의해 NA로 처리된다.

여기까지 배운 내용으로 대략 75% 정도의 데이터 파일을 불러올 수 있다. 또한 탭으로 구분된 파일의 경우에는 read_tsv() 함수를 사용함으로써, 또는 고정간격 파일read_fwf() 함수를 사용하여 불러오는 데도 적용할 수 있다.

이제 좀 더 복잡한 파일을 읽으려면 readr 패키지가 각 열에 대한 데이터 타입을 변경하여 파싱하는 방법에 대해 자세히 학습해야 한다.

1.2.3.4 base R과의 비교

R을 이전에 사용하였다면, read.csv()를 비교해 볼 필요가 있다. base 패키지의 read.*() 함수보다 readr 패키지의 **read_*()** 함수가 좋은 유용한데 그 이유는 다음과 같다.

  • 첫쨰로, 일반적으로 base 패키지의 read.*() 함수보다 readr 패키지의 **read_*() 함수가 데이터 파일을 불러오는데 훨씬 더(~10배) 빠르다는 것이다. 데이터 파일을 불러오는데 시간이 오래 걸리는 작업은 진행 표시줄을 통해 상황을 알 수 있게도 해 준다. 만일 빅 데이터의 경우는 data.table 패키지에 있는 fread()** 함수를 사용하길 권한다. 이 함수는 tidyverse에는 잘 어울리지는 않지만, 대규모의 데이터 파일을 불러오는 데에는 훨씬 더 빠르다.
  • 둘째, base 패키지의 read.() 함수는 데이터 프레임을 생성하는 반면에, readr 패키지의 read_() 함수는 티블(tibble)을 생성해 준다는 것이다. 문자 벡터를 팩터형으로 변환하지도 않고(R version 4.0 이후에는 문자형 열의 factor 형 변환은 옵션이 되었다), 행 이름을 사용하지도 않고, 열 이름을 변경하지도 않는다. base R의 **read.*()** 함수들은 데이터를 원치 않는 형태로 강제 변환하기도 하고, 변경하기도 하는 경우가 있기 때문에 늘 불편하다.
  • 셋째, **read_*() 함수는 좀 더 재현 가능하다는 것이다. base R의 read.*()** 함수는 운영체제 및 환경 변수의 일부 동작을 상속하기 때문에 자신의 컴퓨터에서 작동하는 불러오기 코드가 다른 컴퓨터에서 작동하지 않을 수도 있다.

1.2.4 read_csv()의 예

불러올 데이터 파일에서 각 줄의 데이터 항목들이 컴마(,)로 분리된 경우에는 read_csv() 함수를 사용하여 파일을 불러올 수 있다.

다음은 인라인 csv 파일을 data1/out 폴더에 file.csv로 저장한 다음, 이를 read_csv() 함수로 불러오는 예이다.

write_file(x = "a, b, c\n1,2,3\n4, 5, NA", 
           path="data1/out/file.csv")                         # file.csv 파일의 생성
## Warning: The `path` argument of `write_file()` is deprecated as of readr 1.4.0.
## Please use the `file` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
data <- read_csv("data1/out/file.csv")                        # file.csv 파일 불러오기
## 
## -- Column specification --------------------------------------------------------
## cols(
##   a = col_double(),
##   b = col_double(),
##   c = col_double()
## )
data
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5    NA

1.2.5 read_csv2()의 예

불러올 데이터 파일에 있는 각 줄의 데이터가 세미콜론(;)로 분리되어 있는 경우 read_csv2() 함수를 이용하여 불러올 수 있다.

write_file(x = "a; b; c\n1; 2; 3\n4; 5; NA", 
           path="data1/out/file2.csv")                          # file2.csv 파일의 생성
data2 <- read_csv2("data1/out/file2.csv")                       # file2.csv 파일 불러오기
## i Using ',' as decimal and '.' as grouping mark. Use `read_delim()` for more control.
## 
## -- Column specification --------------------------------------------------------
## cols(
##   a = col_double(),
##   b = col_double(),
##   c = col_double()
## )
data2
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5    NA

1.2.6 read_delim()의 예

불러올 데이터 파일의 각 줄에 이는 데이터가 임의의 구분자를 구분되어 있는 경우. 예를 들어 선문자(|)를 구분자로 되어 있는 경우 다음과 같이 파일을 저장하고 read_delim() 함수로 불러올 수 있다.

write_file(x = "a|b|c\n1|2|3\n4|5|NA", path="data1/out/file.txt")      # file.txt 파일의 생성
data3 <- read_delim("data1/out/file.txt", delim="|" )                  # file.txt 파일 불러오기
## 
## -- Column specification --------------------------------------------------------
## cols(
##   a = col_double(),
##   b = col_double(),
##   c = col_double()
## )
data3
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5    NA

1.2.7 read_fwf()의 예

불러올 데이터 파일의 각 줄에 있는 데이터가 고정 너비 간격으로 분리되어 있는 경우 read_fwf() 함수를 이용하면 된다.

이를 이해하기 하기 실습을 위한 데이터 파일을 하나 생성해 보자.

write_file(x = "2 4 6\n1 2 3\n4 5 NA", path="data1/out/file.fwf")     # file.fwf 파일의 생성

1.2.7.1 비어 있는 컬럼의 위치 추측 : fwf_empty() 함수 이용

data4 <- read_fwf("data1/out/file.fwf", fwf_empty("data1/out/file.fwf", col_names = c("V1", "V2", "V3")))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V2 = col_double(),
##   V3 = col_double()
## )
data4
## # A tibble: 3 x 3
##      V1    V2    V3
##   <dbl> <dbl> <dbl>
## 1     2     4     6
## 2     1     2     3
## 3     4     5    NA

1.2.7.2 필드의 너비 벡터 이용 : fwf_widths() 함수 이용

data5 <- read_fwf("data1/out/file.fwf", fwf_widths(c(2, 2, 2), col_names = c("V1", "V2", "V3")))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V2 = col_double(),
##   V3 = col_double()
## )
## Warning: 2 parsing failures.
## row col expected actual                 file
##   1  V3  1 chars      1 'data1/out/file.fwf'
##   2  V3  1 chars      1 'data1/out/file.fwf'
data5
## # A tibble: 3 x 3
##      V1    V2    V3
##   <dbl> <dbl> <dbl>
## 1     2     4     6
## 2     1     2     3
## 3     4     5    NA

1.2.7.3 시작과 마침 위치를 요소로 하는 벡터 이용 : fwf_positions() 함수 이용

data6 <- read_fwf("data1/out/file.fwf", fwf_positions(c(1, 5), c(2, 7), c("V1", "V3")))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V3 = col_double()
## )
## Warning: 3 parsing failures.
## row col expected actual                 file
##   1  V3  1 chars      1 'data1/out/file.fwf'
##   2  V3  1 chars      1 'data1/out/file.fwf'
##   3  V3  2 chars      2 'data1/out/file.fwf'
data6
## # A tibble: 3 x 2
##      V1    V3
##   <dbl> <dbl>
## 1     2     6
## 2     1     3
## 3     4    NA

1.2.7.4 시작과 마침 위치에 대한 이름 붙여진 인수 사용 : fwf_cols() 함수 이용

data7 <- read_fwf("data1/out/file.fwf", fwf_cols(V1 = c(1, 1), V3 = c(5, 5)))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V3 = col_character()
## )
data7
## # A tibble: 3 x 2
##      V1 V3   
##   <dbl> <chr>
## 1     2 6    
## 2     1 3    
## 3     4 N
  • data7의 경우 마지막 데이터가 NA(결측치)로 V3 = C(5,5)에 의해 첫 글자 N만 읽어 들이게 되고, V3 컬럼은 문자형이 된다.

1.2.7.5 컬럼 너비에 대한 이름 붙여진 인수 사용 : fwf_cols() 함수 이용

data8 <- read_fwf("data1/out/file.fwf", fwf_cols(V1 = 2, V2 = 2, V3 = 1))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V2 = col_double(),
##   V3 = col_character()
## )
data8
## # A tibble: 3 x 3
##      V1    V2 V3   
##   <dbl> <dbl> <chr>
## 1     2     4 6    
## 2     1     2 3    
## 3     4     5 N
  • 앞의 data7과 같은 현상임.

1.2.7.6 연습문제

데이터가 다음과 같이 고정 너비 간격으로 분리된 경우 (“file1.fwf”) 위의 각각의 경우로 데이터를 불러와라.

11aa222
33bb444
55cc666
  • 예제의 풀이 : 데이터 파일의 생성
write_file(x = "11aa222\n33bb444\n55cc666", path="data1/out/file1.fwf")     # file1.fwf 파일의 생성
  • 데이터 파일 불러오기
## 1. Guess based on position of empty columns
d1 <- read_fwf("data1/out/file1.fwf", fwf_empty("data1/out/file1.fwf", col_names = c("V1", "V2", "V3")))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_character(),
##   V2 = col_character(),
##   V3 = col_character()
## )
## Warning: 3 parsing failures.
## row col  expected    actual                  file
##   1  -- 3 columns 1 columns 'data1/out/file1.fwf'
##   2  -- 3 columns 1 columns 'data1/out/file1.fwf'
##   3  -- 3 columns 1 columns 'data1/out/file1.fwf'
View(d1)
# 2. A vector of field widths
d2 <- read_fwf("data1/out/file1.fwf", fwf_widths(c(2, 2, 3), col_names = c("V1", "V2", "V3")))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V2 = col_character(),
##   V3 = col_double()
## )
d2
## # A tibble: 3 x 3
##      V1 V2       V3
##   <dbl> <chr> <dbl>
## 1    11 aa      222
## 2    33 bb      444
## 3    55 cc      666
# 3. Paired vectors of start and end positions
d3 <- read_fwf("data1/out/file1.fwf", fwf_positions(c(1, 5), c(2, 7), c("V1", "V3")))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V3 = col_double()
## )
d3
## # A tibble: 3 x 2
##      V1    V3
##   <dbl> <dbl>
## 1    11   222
## 2    33   444
## 3    55   666
# 4. Named arguments with start and end positions
d4 <- read_fwf("data1/out/file1.fwf", fwf_cols(V1 = c(1, 2), V3 = c(5, 7)))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V3 = col_double()
## )
d4
## # A tibble: 3 x 2
##      V1    V3
##   <dbl> <dbl>
## 1    11   222
## 2    33   444
## 3    55   666
# 5. Named arguments with column widths
d5 <- read_fwf("data1/out/file1.fwf", fwf_cols(V1 = 2, V2 = 2, V3 = 3))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   V1 = col_double(),
##   V2 = col_character(),
##   V3 = col_double()
## )
d5
## # A tibble: 3 x 3
##      V1 V2       V3
##   <dbl> <chr> <dbl>
## 1    11 aa      222
## 2    33 bb      444
## 3    55 cc      666

1.2.8 read_tsv()의 예

불러오 데이터 파일의 각 줄에 있는 데이터 항목들이 탭(\t)으로 분리되어 있는 경우에는 read_tsv() 함수를 이용하여 데이터 파일을 불러오면 된다.

write_file(x = "a\tb\tc\n1\t2\t3\n4\t5\tNA", path="data1/out/file.tsv")      # file.tsv 파일의 생성
data9 <- read_tsv("data1/out/file.tsv")                                      # file.tsv 파일 불러오기
## 
## -- Column specification --------------------------------------------------------
## cols(
##   a = col_double(),
##   b = col_double(),
##   c = col_double()
## )
data9
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5    NA

연습문제

  1. 필드(데이터 항목)가 “|” 로 분리된 파일을 읽으려면 어떤 함수를 사용하겠는가?

    • delim="|"를 인수로 하는 read_delim() 함수를 사용한다.
file <- "data1/dates_delimeter.csv"
read_delim(file, delim = "|")
## 
## -- Column specification --------------------------------------------------------
## cols(
##   fmt1 = col_character(),
##   fmt2 = col_character(),
##   fmt3 = col_date(format = ""),
##   fmt4 = col_double(),
##   decision_time = col_character()
## )
## # A tibble: 3 x 5
##   fmt1     fmt2             fmt3           fmt4 decision_time             
##   <chr>    <chr>            <date>        <dbl> <chr>                     
## 1 01/15/89 December 8, 2015 2015-02-27 20090101 Approved 10-10-15 07:15:55
## 2 02/13/92 January 22, 2012 2016-11-15 20080819 Denied 09-27-11 14:57:23  
## 3 03/15/84 March 3, 2010    2017-12-25 20071011 Approved 04-24-15 02:03:03

** data 디렉토리의 dates_delimeter1.csv ~ dates_delimeter5.csv 파일들도 연습해 보기 바람. **

  1. read_csv()read_tsv() 가 공통으로 가진 인수는 file, skip, comment 외에 또 무엇이 있는가?

    • 두 함수의 공통 인수를 찾기 위해 다음을 수행한다.
union(names(formals(read_csv)), names(formals(read_tsv)))
##  [1] "file"            "col_names"       "col_types"       "locale"         
##  [5] "na"              "quoted_na"       "quote"           "comment"        
##  [9] "trim_ws"         "skip"            "n_max"           "guess_max"      
## [13] "progress"        "skip_empty_rows"
  • col_namescol_types : 컬럼 이름을 지정과 그 컬럼을 어떻게 parse할 지를 지정한다.
  • locale : 인코딩과 관련한 것들의 지정 또 십진수 표시를 “,”로 할 찌 “.”으로 할 지의 지정에 사용된다.
  • naquoted_na : 벡터를 파싱할 때 어떤 문자열이 결측치로 처리될 지를 지정한다.
  • trim_ws : 파싱하기 전에 셀의 앞 뒤로 공백문자를 제거
  • n_max : 읽어 들일 행의 갯수 지정
  • guess_max : 컬럼 형을 추측할 때 몇 개의 행을 사용할 지를 지정
  • progress : 진행 막대를 표시할 지를 결정
  1. read_fwf() 에서 가장 중요한 인수는 무엇인가?
    • 고정너비 형식의 파일을 불러오는 read_fwf()의 가장 중요한 인수는 데이터 열의 시작과 끝을 함수에게 알려주는 col_position= 인수이다.
  2. CSV 파일의 문자열에 쉼표가 포함되는 경우가 있다. 그것들이 문제를 일으 키지 않게 하려면 " 혹은 '와 같은 인용 문자로 둘러싸일 필요가 있다. read_csv() 는 인용 문자가 "라고 가정한다. 이를 변경하려면 read_delim() 을 대신 사용하면 된다. 다음 텍스트를 데이터프레임으로 읽으려면 어떤 인수를 설정해야하는가?
x <- "x,y\n1,'a,b'"
read_delim(x, ",", quote = "'")
## # A tibble: 1 x 2
##       x y    
##   <dbl> <chr>
## 1     1 a,b
  • read_delim()함수를 사용하려면, 구분자를 지정해야 한다. 이 경우의 구분자는 “,”이며, quote =인수의 값은 “‘“.
x <- "x,y\n1,'a,b'"
read_delim(x, ",", quote = "'")
## # A tibble: 1 x 2
##       x y    
##   <dbl> <chr>
## 1     1 a,b
  • x“,” 기호로 데이터 요소들을 구분하고, 문자열 데이터는 “'" 로 묶여 있음(quote="'")을 지정한다.
    • x, y : 컬럼 제목 xy
    • \n : 줄 바꾸기
    • 1, ‘a,b’ : 데이터 요소로 1a,b
  1. 다음 각 인라인 CSV 파일에 어떤 문제가 있는지 확인하라. 코드를 실행하면 어떻게 되는가?
read_csv("a,b\n1,2,3\n4,5,6")
## Warning: 2 parsing failures.
## row col  expected    actual         file
##   1  -- 2 columns 3 columns literal data
##   2  -- 2 columns 3 columns literal data
## # A tibble: 2 x 2
##       a     b
##   <dbl> <dbl>
## 1     1     2
## 2     4     5
read_csv("a,b,c\n1,2\n1,2,3,4")
## Warning: 2 parsing failures.
## row col  expected    actual         file
##   1  -- 3 columns 2 columns literal data
##   2  -- 3 columns 4 columns literal data
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2    NA
## 2     1     2     3
read_csv("a,b\n\"1")
## Warning: 2 parsing failures.
## row col                     expected    actual         file
##   1  a  closing quote at end of file           literal data
##   1  -- 2 columns                    1 columns literal data
## # A tibble: 1 x 2
##       a b    
##   <dbl> <chr>
## 1     1 <NA>
read_csv("a,b\n1,2\na,b")
## # A tibble: 2 x 2
##   a     b    
##   <chr> <chr>
## 1 1     2    
## 2 a     b
read_csv("a;b\n1;3")
## # A tibble: 1 x 1
##   `a;b`
##   <chr>
## 1 1;3
read_csv2("a;b\n1;3")
## i Using ',' as decimal and '.' as grouping mark. Use `read_delim()` for more control.
## # A tibble: 1 x 2
##       a     b
##   <dbl> <dbl>
## 1     1     3
  • 두 개의 열만 “a”와 “b”라는 헤더가 있는데, 데이터 요소는 3개이다. 따라서 마지막 요소의 값은 자동 삭제가 된다.

    read_csv("a,b\n1,2,3\n4,5,6")
    ## Warning: 2 parsing failures.
    ## row col  expected    actual         file
    ##   1  -- 2 columns 3 columns literal data
    ##   2  -- 2 columns 3 columns literal data
    ## # A tibble: 2 x 2
    ##       a     b
    ##   <dbl> <dbl>
    ## 1     1     2
    ## 2     4     5
  • 셋 째의 경우는 의도가 분명치 않다. "1 은 삭제되는데, 이는 로 닫히지 않았기 때문이다 그리고 a컬럼은 정수형으로 처리된다.

    read_csv("a,b\n\"1")
    ## Warning: 2 parsing failures.
    ## row col                     expected    actual         file
    ##   1  a  closing quote at end of file           literal data
    ##   1  -- 2 columns                    1 columns literal data
    ## # A tibble: 1 x 2
    ##       a b    
    ##   <dbl> <chr>
    ## 1     1 <NA>
  • a”와 “b” 모두는 비수치 문자열을 포함하고 있기 때문에 모두 문자 벡터로 처리된다. 이는 의도적으로 각각의 열에 “1,2”와 “a,b” 값을 할당하는 것이다.

    read_csv("a,b\n1,2\na,b")
    ## # A tibble: 2 x 2
    ##   a     b    
    ##   <chr> <chr>
    ## 1 1     2    
    ## 2 a     b
  • 데이터가 컴마(,)가 아닌 세미콜론(;)으로 구분되어 있으면, read_csv2()함수를 이용한다:

    read_csv("a;b\n1;3")
    ## # A tibble: 1 x 1
    ##   `a;b`
    ##   <chr>
    ## 1 1;3
    read_csv2("a;b\n1;3")
    ## i Using ',' as decimal and '.' as grouping mark. Use `read_delim()` for more control.
    ## # A tibble: 1 x 2
    ##       a     b
    ##   <dbl> <dbl>
    ## 1     1     3
    • 첫 번째의 경우, read_csv() 함수는 a;b가 컬럼 제목이고, 1;3은 이 컬럼의 데이터인 것으로 읽는다.
    • 두 번째의 경우, read_csv2() 함수는 데이터 구분자로 세미콜론(;)을 사용하기 때문에, a;ba컬럼과 b컬럼으로, 1;3은 이 컬럼의 데이터로 13인 것으로 읽는다.

1.2.9 한글 파일 불러오기

불러올 데이터 파일에 한글이 있는 data1/korean_data.csv 파일을 다음과 같이 read_csv() 함수로 불러와 보자.

data_kor <- read_csv("data1/korean_data.csv")
## 
## -- Column specification --------------------------------------------------------
## cols(
##   `<U+623C><U+3E30><U+02FF>愼<U+3E61>` = col_double(),
##   `<U+633C><U+3E31>愼<U+3E36><U+633C><U+3E31><U+643C><U+3E36>` = col_double(),
##   `<U+623C><U+3E30><U+6CF2>` = col_double(),
##   `<U+623C><U+3E30><U+653C><U+3E36><U+623C><U+3E61><U+633C><U+3E66>` = col_double(),
##   `<U+633C><U+3E30><U+663C><U+3E63><U+623C><U+3E33><U+623C><U+3E32>` = col_double(),
##   `<U+633C><U+3E30><U+663C><U+3E63><U+623C><U+3E61><U+633C><U+3E66>` = col_double(),
##   `<U+633C><U+3E33><U+6CF2>` = col_double(),
##   `<U+633C><U+3E33><U+653C><U+3E36><U+623C><U+3E61><U+633C><U+3E66>` = col_double(),
##   `<U+623C><U+3E30>愼<U+3E64><U+623C><U+3E66><U+663C><U+3E38>` = col_double(),
##   `<U+623C><U+3E30><U+653C><U+3E36><U+623C><U+3E31><U+653C><U+3E32>` = col_double(),
##   `<U+623C><U+3E63><U+623C><U+3E63><U+633C><U+3E31><U+623C><U+3E65>` = col_double(),
##   `<U+623C><U+3E66><U+653C><U+3E66><U+623C><U+3E62><U+653C><U+3E61>` = col_double(),
##   `<U+623C><U+3E34><U+653C><U+3E62><U+633C><U+3E30><U+663C><U+3E63>` = col_double(),
##   `<U+623C><U+3E31>愼<U+3E34><U+633C><U+3E31><U+643C><U+3E36>` = col_double(),
##   `<U+633C><U+3E30><U+633C><U+3E65>o` = col_double(),
##   `<U+623C><U+3E34>뱸` = col_double(),
##   `<U+623C><U+3E61>λ<U+653C><U+3E61>` = col_double()
## )
data_kor
## Error in nchar(x[is_na], type = "width"): invalid multibyte string, element 1
  • 한글이 제대로 표시가 되지 않는다.
  • 더불어 error 메시지가 출력된다.

이와 같이 한글이 있는 데이터 파일을 불러올 경우에는 locale 인수를 다음과 같이 지정하여 데이터 파일을 불러와야 한다.

data_kor <- read_csv("data1/korean_data.csv", locale = locale('ko', encoding='euc-kr'))
## 
## -- Column specification --------------------------------------------------------
## cols(
##   검역 = col_double(),
##   제주 = col_double(),
##   경남 = col_double(),
##   경북 = col_double(),
##   전남 = col_double(),
##   전북 = col_double(),
##   충남 = col_double(),
##   충북 = col_double(),
##   강원 = col_double(),
##   경기 = col_double(),
##   세종 = col_double(),
##   울산 = col_double(),
##   대전 = col_double(),
##   광주 = col_double(),
##   인천 = col_double(),
##   대구 = col_double(),
##   부산 = col_double()
## )
data_kor
## # A tibble: 1 x 17
##    검역  제주  경남  경북  전남  전북  충남  충북  강원  경기  세종  울산  대전
##   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     7     0     1     4     0     0     0     1     1    14     0     1     0
## # ... with 4 more variables: 광주 <dbl>, 인천 <dbl>, 대구 <dbl>, 부산 <dbl>