Import

R for Data Science (2e) by Wickham, Çetinkaya-Rundel & Grolemund

Published

September 4, 2026

자세한 데이터 import에 대해서는 R for Data Science (2판) / Data import 참고

파일 경로

작업 폴더(workspace)를 열어두고 그 안의 파일을 상대경로로 지시하는 것이 원칙 (절대경로는 다른 컴퓨터에서 깨짐)

read_csv("data/altruism.csv") # 작업 폴더 아래 data 폴더의 파일
getwd() # 현재 작업 폴더 확인
Tip

Positron에서는 Explorer(왼쪽 패널)에서 CSV/Parquet 파일을 클릭하면 코드 없이도 Data Explorer로 바로 열어볼 수 있음. 파일의 내용과 열 이름을 먼저 눈으로 확인한 뒤 읽어들이면 실수가 줄어듦

Text files: csv

readr 패키지(tidyverse에 포함)

read_csv(), write_csv()

  • R 기본 함수 read.csv()를 개선 (빠르고, tibble로 반환하며, 문자열을 factor로 바꾸지 않음)
  • 다양한 옵션은 ?read_csv, ?write_csv 참고

csv 파일 읽기

altruism.csv 파일 링크

library(tidyverse)

helping <- read_csv("data/altruism.csv") # readr 패키지의 함수
helping
# A tibble: 120 × 12
     id pho_1 pho_2 pho_3   sex   age emp_q20 emp_q22 emp_q23 emp_q24 emp_q25
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1     1    95    95    95     1  2004      80      NA      80      80      70
2     2    58    62    NA     0  2003      62      58      59      57      56
3     3   100    50    50    NA  2003      90      51      51      51      52
4     4    77    77    64     1  2004      66      72      88      82      67
5     5    NA    NA    NA    NA    NA      NA      NA      NA      NA      NA
6     6   100    75   100     0  2004     100      60      70      55      70
# ℹ 114 more rows
# ℹ 1 more variable: emp_q26 <dbl>

읽어들인 직후 출력되는 column specification은 각 열의 타입을 어떻게 추측했는지 알려줌.
의도와 다르게 추측된 열이 있는지 항상 확인할 것

Note

read_csv()의 자주 사용되는 옵션

read_csv("data/file.csv", skip = 2)      # 첫 2줄 스킵
read_csv("data/file.csv", na = ".")      # 결측치가 .으로 기록된 파일
read_csv("data/file.csv", na = c("", "NA", "999"))
read_csv("data/file.csv", show_col_types = FALSE) # 타입 추측 메시지를 끔

# 열 타입을 직접 지정 (추측이 틀렸을 때)
read_csv("data/file.csv", col_types = cols(id = col_character()))

# 열 이름이 없는 파일
read_csv("data/file.csv", col_names = c("id", "wage", "age"))
한글이 깨질 때

국내에서 만들어진 csv 파일은 UTF-8이 아니라 CP949(EUC-KR)로 저장된 경우가 많음

read_csv("data/file.csv", locale = locale(encoding = "EUC-KR"))

guess_encoding("data/file.csv") # 인코딩 추측

csv 파일 쓰기

write_csv(): 단, 쓰기를 하면서 변수 타입(factor의 레벨 등)이 소멸됨

write_csv(helping, file = "data/helping_new.csv")
Tip

R에서만 다시 쓸 파일이라면 타입이 그대로 보존되는 write_rds() / read_rds()가 편함

write_rds(helping, "data/helping.rds")
helping <- read_rds("data/helping.rds")

Excel spreadsheets

readxl package (tidyverse에 포함되어 있으나 자동으로 로드되지는 않음)

read_excel(), read_xlsx(), read_xls()

엑셀 파일 읽기

students.xlsx 파일 링크

library(readxl) # install.packages("readxl")
stud <- read_xlsx("data/students.xlsx")

# 또는
stud <- readxl::read_xlsx("data/students.xlsx")

stud
# A tibble: 1,000 × 93
  stu_id sch_id sstratid   sex  race ethnic bys42a bys42b bys44a bys44b bys44c
   <dbl>  <dbl>    <dbl> <dbl> <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 124966   1249        1     2     4      1      3      4      2      4      4
2 124972   1249        1     1     4      1      4      5      1      3      3
3 175551   1755        1     2     3      0     NA      3      2      3      3
4 180660   1806        1     1     4      1      2     NA      1      4      4
5 180672   1806        1     2     4      1      2      3      1      4      3
6 298885   2988        2     1     3      0      5      4      2      3      3
# ℹ 994 more rows
# ℹ 82 more variables: bys44d <dbl>, bys44e <dbl>, bys44f <dbl>, bys44g <dbl>,
#   bys44h <dbl>, bys44i <dbl>, bys44j <dbl>, bys44k <dbl>, bys44l <dbl>,
#   bys44m <dbl>, bys48a <dbl>, bys48b <dbl>, bys79a <dbl>, byfamsiz <dbl>,
#   famcomp <dbl>, bygrads <dbl>, byses <dbl>, byfaminc <dbl>, parocc <dbl>,
#   bytxrstd <dbl>, bytxmstd <dbl>, bytxsstd <dbl>, bytxhstd <dbl>,
#   bypared <dbl>, bytests <dbl>, par_inv <dbl>, f1s36a1 <dbl>, …
Note

시트는 위치 또는 이름으로 지정

read_excel("salaries.xlsx", sheet = 2) # 기본값은 sheet = 1
read_excel("salaries.xlsx", sheet = "personnel")

excel_sheets("salaries.xlsx") # 시트 이름 목록 확인

# 표가 시트 한가운데 있는 경우 범위를 지정
read_excel("salaries.xlsx", range = "B3:F102")

엑셀 파일로 쓰려면 writexl::write_xlsx(df, "out.xlsx")

Warning

엑셀 파일은 한 열 안에 숫자와 문자가 섞여 있는 경우가 흔함.
이때 read_excel()은 열 전체를 문자로 읽거나 일부를 NA로 만들 수 있으므로, 읽은 직후 glimpse()로 타입을 확인할 것

Statistical packages

haven 패키지 (tidyverse에 포함되어 있으나 자동으로 로드되지는 않음)

  • SPSS: read_sav(), read_por()
  • Stata: read_dta()
  • SAS: read_sas(), read_xpt()

students-shorter.sav 파일 링크

library(haven) # install.packages("haven")
stud_spss <- read_sav("data/students-shorter.sav")

# 또는
stud_spss <- haven::read_sav("data/students-shorter.sav")

stud_spss
# A tibble: 1,000 × 93
  stu_id    sch_id    sstratid sex     race    ethnic  bys42a   bys42b   bys44a 
  <dbl+lbl> <dbl+lbl> <dbl+lb> <dbl+l> <dbl+l> <dbl+l> <dbl+lb> <dbl+lb> <dbl+l>
1 124966    1249      1        2 [Fem… 4 [Whi… 1 [whi…  3 [2-3…  4 [3-4… 2 [Agr…
2 124972    1249      1        1 [Mal… 4 [Whi… 1 [whi…  4 [3-4…  5 [4-5… 1 [Str…
3 175551    1755      1        2 [Fem… 3 [Bla… 0 [blk… NA        3 [2-3… 2 [Agr…
4 180660    1806      1        1 [Mal… 4 [Whi… 1 [whi…  2 [1-2… NA       1 [Str…
5 180672    1806      1        2 [Fem… 4 [Whi… 1 [whi…  2 [1-2…  3 [2-3… 1 [Str…
6 298885    2988      2        1 [Mal… 3 [Bla… 0 [blk…  5 [4-5…  4 [3-4… 2 [Agr…
# ℹ 994 more rows
# ℹ 84 more variables: bys44b <dbl+lbl>, bys44c <dbl+lbl>, bys44d <dbl+lbl>,
#   bys44e <dbl+lbl>, bys44f <dbl+lbl>, bys44g <dbl+lbl>, bys44h <dbl+lbl>,
#   bys44i <dbl+lbl>, bys44j <dbl+lbl>, bys44k <dbl+lbl>, bys44l <dbl+lbl>,
#   bys44m <dbl+lbl>, bys48a <dbl+lbl>, bys48b <dbl+lbl>, bys79a <dbl+lbl>,
#   byfamsiz <dbl+lbl>, famcomp <dbl+lbl>, bygrads <dbl+lbl>, byses <dbl+lbl>,
#   byfaminc <dbl+lbl>, parocc <dbl>, bytxrstd <dbl+lbl>, bytxmstd <dbl+lbl>, …

Labelled 변수

SPSS 데이터의 변수는 값(1, 2, 3…)과 그 값의 의미(label)를 함께 가지고 있어서, R에서는 <dbl+lbl>이라는 특수한 타입으로 읽힘

stud_spss |>
  select(ethnic)
# A tibble: 1,000 × 1
  ethnic            
  <dbl+lbl>         
1 1 [white-asian]   
2 1 [white-asian]   
3 0 [blk,namer,hisp]
4 1 [white-asian]   
5 1 [white-asian]   
6 0 [blk,namer,hisp]
# ℹ 994 more rows

값과 label의 대응은 print_labels()로 확인

print_labels(stud_spss$race)

Labels:
 value                label
     1 Asian/Pacific islndr
     2             Hispanic
     3   Black not Hispanic
     4   White not Hispanic
     5   Amer ind/AK Native
     8              MISSING
print_labels(stud_spss$ethnic)

Labels:
 value          label
     0 blk,namer,hisp
     1    white-asian
     8        missing

labelled 변수는 숫자도 factor도 아닌 어정쩡한 상태이므로, 분석 전에 둘 중 하나로 정리해야 함

(1) factor로 변환: 카테고리 변수로 다룰 때

stud <- stud_spss |>
  mutate(across(c(sex, race, ethnic), haven::as_factor))

stud |> select(stu_id, sex, race, ethnic)
# A tibble: 1,000 × 4
  stu_id    sex    race               ethnic        
  <dbl+lbl> <fct>  <fct>              <fct>         
1 124966    Female White not Hispanic white-asian   
2 124972    Male   White not Hispanic white-asian   
3 175551    Female Black not Hispanic blk,namer,hisp
4 180660    Male   White not Hispanic white-asian   
5 180672    Female White not Hispanic white-asian   
6 298885    Male   Black not Hispanic blk,namer,hisp
# ℹ 994 more rows
stud |> count(race)
# A tibble: 6 × 2
  race                     n
  <fct>                <int>
1 Asian/Pacific islndr    61
2 Hispanic               114
3 Black not Hispanic     100
4 White not Hispanic     704
5 Amer ind/AK Native      10
6 <NA>                    11
Warning

stud_spss |> haven::as_factor()처럼 데이터셋 전체에 적용하면 stu_id, sch_id 같은 ID 변수까지 factor로 바뀌어버림 (SPSS에서는 이들도 labelled 변수임).
필요한 변수만 위와 같이 골라서 변환하거나, 값이 모두 label을 가진 변수만 변환해주는 labelled::unlabelled()를 쓸 것

(2) label을 떼고 순수한 숫자로: 리커트 척도처럼 숫자로 계산할 때

stud2 <- stud_spss |>
  zap_labels() # 값의 label 제거, zap_label(): 변수의 label 제거

stud2
# A tibble: 1,000 × 93
  stu_id sch_id sstratid   sex  race ethnic bys42a bys42b bys44a bys44b bys44c
   <dbl>  <dbl>    <dbl> <dbl> <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 124966   1249        1     2     4      1      3      4      2      4      4
2 124972   1249        1     1     4      1      4      5      1      3      3
3 175551   1755        1     2     3      0     NA      3      2      3      3
4 180660   1806        1     1     4      1      2     NA      1      4      4
5 180672   1806        1     2     4      1      2      3      1      4      3
6 298885   2988        2     1     3      0      5      4      2      3      3
# ℹ 994 more rows
# ℹ 82 more variables: bys44d <dbl>, bys44e <dbl>, bys44f <dbl>, bys44g <dbl>,
#   bys44h <dbl>, bys44i <dbl>, bys44j <dbl>, bys44k <dbl>, bys44l <dbl>,
#   bys44m <dbl>, bys48a <dbl>, bys48b <dbl>, bys79a <dbl>, byfamsiz <dbl>,
#   famcomp <dbl>, bygrads <dbl>, byses <dbl>, byfaminc <dbl>, parocc <dbl>,
#   bytxrstd <dbl>, bytxmstd <dbl>, bytxsstd <dbl>, bytxhstd <dbl>,
#   bypared <dbl>, bytests <dbl>, par_inv <dbl>, f1s36a1 <dbl>, …
Warning

as_factor()는 forcats(tidyverse)에도 같은 이름의 함수가 있어 충돌함.
library(haven) 뒤에는 haven의 것이 우선하지만, 헷갈리지 않으려면 haven::as_factor()로 명시하는 것이 안전함

Note

8 = MISSING처럼 결측을 특정 숫자로 코딩해 둔 경우가 많음. 그대로 두면 평균 계산이 망가지므로 반드시 NA로 바꿔야 함

stud_spss |>
  mutate(race = na_if(race, 8))

labelled 데이터를 본격적으로 다루려면 labelled 패키지 참고 (look_for()로 변수를 검색하는 기능이 유용함)