Menu

R에서 CSV 파일 읽기 (read.csv와 read_csv)

read.csv()로 CSV 파일을 R에 불러오는 방법 - 중요한 인자들, 대부분의 실패를 일으키는 작업 디렉터리 함정, 그리고 readr::read_csv가 값어치를 하는 시점.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

read.csv()는 CSV 파일을 데이터 프레임으로 바꿉니다

R에서 CSV를 읽는 것은 언어에 내장된 함수 호출 한 번이면 됩니다 - 패키지가 필요 없습니다:

sales <- read.csv("sales.csv")

read.csv()는 파일을 읽고, 첫 줄을 열 이름으로 사용하고, 각 열의 타입을 추측한 뒤 데이터 프레임을 반환합니다. 얌전한 파일이라면 이게 전부입니다.

파일이 전혀 없어도 동작을 확인할 수 있습니다. read.csv()text 인자를 통해 CSV 원문 텍스트도 받기 때문입니다 - 같은 파서에 파일 이름 대신 문자열을 먹이는 셈이죠:

임포트한 무엇에든 가장 먼저 실행할 것은 str()입니다: 모든 열과 추측된 타입을 보여 줍니다. 여기서 name은 문자형, score는 정수형, passed는 논리형으로 들어왔습니다 - 모두 값에서 추측한 것입니다. 눈으로 빠르게 확인하려면 head(students)가 첫 몇 행을, nrow(students)가 행 수를 보여 줍니다. 숫자일 것으로 기대한 열이 chr로 나타난다면 그 열에 숫자가 아닌 무언가가 있는 것입니다 - 엉뚱한 주석, "N/A", 천 단위 구분 기호 같은 것이죠 - 그리고 바로 그때가 고칠 순간입니다. 그래프를 세 개나 그린 뒤가 아니라요.

중요한 인자들

read.csv()에는 수십 개의 매개변수가 있지만, 실제로 쓰는 것은 다섯 개쯤입니다.

header - 첫 줄이 열 이름인지 여부입니다. 기본값은 TRUE입니다. 파일이 데이터로 곧장 시작한다면 header = FALSE를 전달하세요. 그러면 R이 열 이름을 V1, V2, ...로 붙입니다.

sep - 필드 구분자이며 기본값은 ","입니다. 유럽의 상당 지역에서는 쉼표가 소수점이기 때문에 CSV를 세미콜론으로 구분해 씁니다. R은 정확히 그 경우를 위한 변형을 제공합니다: read.csv2()sep = ";"dec = ","를 사용합니다:

키가 제대로 된 숫자로 나옵니다 - read.csv21,63이 1.63을 뜻한다는 것을 알았습니다. 이 파일에 평범한 read.csv를 썼다면 뒤엉킨 열 하나만 얻었을 것입니다. 소수점 역할을 하는 쉼표에서 올바르게 나눌 방법이 없기 때문입니다.

na.strings - 어떤 문자열을 결측으로 볼지 지정합니다. 기본적으로는 "NA"만 결측값이 됩니다. 실제 내보내기 파일은 결측 데이터를 빈 셀, "missing", "-", "NULL" 등으로 씁니다 - 이를 선언하지 않으면 텍스트로 들어와 열 전체를 문자형으로 끌어내립니다:

na.strings를 제대로 주면 빈 값이 진짜 NA가 되고 score는 수치형으로 남습니다. 그렇지 않으면 "missing"은 그저 단어이고 열은 텍스트가 됩니다.

skip - 데이터가 시작되기 전에 무시할 줄 수입니다. 내보내기 파일은 실제 표 위에 제목 줄을 한두 개 넣기를 좋아합니다. skip = 2가 그것을 건너뜁니다.

colClasses - R이 추측하게 두는 대신 열 타입을 강제합니다. 대표적인 피해자는 앞자리 0이 있는 값들 - 우편번호, 전화번호, 상품 ID - 인데, R의 추측기가 이를 숫자로 읽어 0을 지워 버립니다:

00501501이 되었습니다. 데이터는 파일에서 옳았지만 R 안에서 조용히 틀려졌습니다. colClasses = c("integer", "character")는 각 열이 무엇인지 순서대로 파서에 알려 주고, 그러면 0이 살아남습니다.

이제는 필요 없어진 인자가 하나 있습니다: stringsAsFactors. R의 역사 대부분 동안 read.csv()는 별도로 지정하지 않는 한 모든 텍스트 열을 팩터로 변환했고, 이는 엄청난 혼란을 일으켰습니다. R 4.0부터는 기본값이 FALSE라 텍스트는 텍스트로 남습니다. 오래된 튜토리얼 곳곳에서 여전히 stringsAsFactors = FALSE를 보게 될 텐데, 최신 R에서는 무해하지만 불필요합니다.

파일 경로: read.csv가 실패하는 1위 이유

R 학습자라면 첫 주에 만나는 오류입니다:

Error in file(file, "rt") : cannot open the connection
In addition: Warning message:
cannot open file 'sales.csv': No such file or directory

파일은 분명 존재합니다 - 파일 관리자에서 지금 보고 있으니까요. 하지만 R은 거기를 보고 있지 않습니다. "sales.csv" 같은 맨 파일 이름은 R의 작업 디렉터리 를 기준으로 해석되는데, 그 디렉터리는 보통 여러분의 파일이 있는 폴더가 아닙니다. 두 줄이면 진단됩니다:

getwd()                    # where R is actually looking
file.exists("sales.csv")   # FALSE means the path is wrong, full stop

file.exists()FALSE라면 아무리 다시 실행해도 소용없습니다 - 경로를 고치세요. 전체 경로를 주거나(read.csv("C:/Users/ada/data/sales.csv") - 슬래시는 Windows에서도 동작하며 역슬래시보다 안전합니다), setwd()로 R의 작업 디렉터리를 데이터 폴더로 옮기면 됩니다. 작업 디렉터리가 무엇인지, 프로젝트가 이를 어떻게 관리하는지, 스크립트 안의 setwd()가 왜 눈총을 받는지는 작업 디렉터리에서 다룹니다.

file.exists()를 반사 신경으로 만드세요. "알 수 없는 임포트 실패"를 1초 만에 "경로 오타"로 바꿔 줍니다.

URL에서 곧바로 CSV 읽기

read.csv()는 파일 이름을 받는 자리라면 어디서든 URL도 받고, 파일을 대신 내려받아 줍니다:

url <- "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
penguins <- read.csv(url)
str(penguins)

튜토리얼이나 공개 데이터셋에 편리합니다 - 다운로드 단계도, 경로 문제도 없습니다. 대신 스크립트가 네트워크와 그 URL의 생존에 의존하게 됩니다. 자주 다시 실행할 작업이라면 한 번 내려받아 로컬 사본을 읽으세요.

readr::read_csv - 더 빠르고 말이 많은 대안

tidyverse는 자체 CSV 리더를 readr 패키지로 제공합니다: read_csv()(점이 아니라 밑줄). 요즘 읽게 될 R 코드 대부분이 이것을 쓰므로 알아 둘 가치가 있습니다:

install.packages("readr")   # once
library(readr)              # every session

flights <- read_csv("flights.csv")

read.csv()와의 실질적인 차이는 이렇습니다:

  • 속도 - 수십만 행짜리 파일에서 눈에 띄게 빠릅니다.
  • 티블을 반환합니다 - 콘솔을 가득 채우는 대신 간결한 미리보기를 출력하는 현대화된 데이터 프레임입니다.
  • 추측 결과를 알려 줍니다 - 읽은 뒤 각 열의 감지된 타입을 출력하므로, 숫자일 것으로 기대한 열이 문자형으로 파싱되었다면 나중에 놀라는 대신 즉시 보입니다.
  • 열 이름을 망가뜨리지 않습니다 - read.csv()first name 같은 헤더를 first.name으로 바꾸지만 read_csv()는 그대로 둡니다.

작은 파일이면 어느 함수든 괜찮습니다. 파일이 커지거나 스크립트의 나머지가 어차피 tidyverse라면 read_csv()를 쓰세요. 경로, 구분자(read_csv2()도 있습니다), 결측값 문자열(na =)에 대한 위의 모든 내용은 인자 이름만 조금 다를 뿐 그대로 적용됩니다.

분석이 끝난 뒤 결과를 파일로 내보내는 반대 여정은 write.csv에서 다룹니다.

핵심 정리

  • df <- read.csv("file.csv")는 CSV를 데이터 프레임으로 읽습니다. 곧바로 str()head()로 확인하세요.
  • read.csv(text = "...")는 CSV 문자열을 바로 파싱합니다 - 실험과 작은 예제에 좋습니다.
  • 값어치를 하는 인자들: header, sep(세미콜론이면 read.csv2), na.strings, skip, colClasses.
  • "Cannot open file"은 작업 디렉터리가 생각한 곳이 아니라는 뜻입니다 - getwd()file.exists()가 즉시 판가름합니다.
  • readr::read_csv()는 더 빠른 tidyverse 버전입니다: 티블, 보고되는 열 타입, 손대지 않은 이름.

다음 주제: 아예 평문이 아닌 파일 - readxl 패키지로 엑셀 스프레드시트 읽기.

자주 묻는 질문

R에서 CSV 파일은 어떻게 읽나요?

read.csv("file.csv")로 읽습니다 - 내장 함수라 패키지가 필요 없습니다. CSV의 열마다 하나씩 열을 가진 데이터 프레임을 반환하며 첫 줄을 열 이름으로 사용합니다. 결과를 변수에 할당하세요: df <- read.csv("sales.csv"). 그런 다음 str(df)head(df)로 확인합니다.

read.csv가 'cannot open file: No such file or directory'라고 하는 이유는 무엇인가요?

R이 작업 디렉터리를 기준으로 파일을 찾고 있는데, 그 디렉터리가 파일이 있는 폴더가 아닐 가능성이 큽니다. getwd()로 R이 어디를 보고 있는지 확인하고 file.exists("file.csv")로 실제로 없는지 확인하세요. 전체 경로를 쓰거나 작업 디렉터리를 파일이 있는 폴더로 바꾸면 해결됩니다.

R에서 read.csv와 read_csv의 차이는 무엇인가요?

read.csv()는 base R이라 언제나 쓸 수 있고 평범한 데이터 프레임을 반환합니다. read_csv()는 readr 패키지에서 오며 큰 파일에서 더 빠르고, 티블(tibble)을 반환하며, 열 이름을 절대 건드리지 않고, 추측한 열 타입을 출력해 잘못된 파싱을 즉시 알아챌 수 있게 합니다. 작은 파일이면 어느 쪽이든 괜찮고, 큰 파일이나 tidyverse 파이프라인에서는 read_csv()를 쓰세요.

R에서 세미콜론으로 구분된 CSV는 어떻게 읽나요?

read.csv2("file.csv")를 사용하세요 - 유럽식 관행에 맞게 미리 설정된 read.csv입니다: 세미콜론이 구분자이고 쉼표가 소수점입니다. 아니면 평범한 read.csv()에 sep = ";"(필요하면 dec = ","도)를 전달하세요.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기