7 파일에서 데이터 읽기

7 파일에서 데이터 읽기

데이터가 방대해지면 일일이 키보드로 입력하는 것보다, 외부 파일에서 값을 읽어 들이는 게 훨씬 자연스러워요. R의 입력 기능은 사실 단순하고, 요구사항도 꽤 엄격하고 융통성이 없는 편이에요. R 설계자들의 입장은 분명해요. "입력 파일은 편집기나 Perl 같은 다른 도구로 R 요구사항에 맞게 다듬어 쓸 수 있을 거다"라는 전제가 깔려 있죠. 다행히 이 작업 자체는 보통 아주 간단합니다.

변수들을 주로 데이터 프레임에 담아 쓰시길 강력히 권장하는데, 그렇게 한다면 데이터 프레임 전체를 read.table() 함수 하나로 바로 읽어 들일 수 있어요. 더 원시적인 입력 함수로 scan()도 있는데, 이건 직접 호출해서 쓸 수 있어요.

R로 데이터를 가져오는 일과 내보내는 일을 더 자세히 보고 싶다면, R Data Import/Export를 참고하세요.

출처: R 공식 매뉴얼

본문

7.1 read.table() 함수

외부 파일에서 데이터 프레임 전체를 바로 읽어 들이려면, 보통 해당 파일이 특별한 형태를 갖추고 있어야 해요. 그 형태는 두 가지 규칙으로 요약됩니다.

  • 파일의 첫 줄에는 데이터 프레임에 들어갈 각 변수의 **이름(name)**이 하나씩 있어야 해요.
  • 이후의 각 줄은 첫 항목으로 **행 이름(row label)**을 갖고, 그다음에 각 변수의 값들이 따라옵니다.

만약 파일의 첫 줄에 있는 항목 수가 둘째 줄보다 하나 적다면, R은 위와 같은 배열이라고 간주해요. 그래서 데이터 프레임으로 읽을 파일의 처음 몇 줄은 대략 이렇게 생겼습니다.

Input file form with names and row labels:

     Price    Floor     Area   Rooms     Age  Cent.heat
01   52.00    111.0      830     5       6.2      no
02   54.75    128.0      710     5       7.5      no
03   57.50    101.0     1000     5       4.2      no
04   57.50    131.0      690     6       8.8      no
05   59.75     93.0      900     5       1.9     yes
...

기본적으로 숫자 항목(행 이름 제외)은 숫자형 변수로 읽히고, 예시의 Cent.heat처럼 숫자가 아닌 변수는 문자형 변수로 읽혀요. 이 동작은 필요하면 바꿀 수 있어요.

이제 read.table() 함수로 데이터 프레임을 바로 읽어 들이면 됩니다.

> HousePrice <- read.table("houses.data")

행 이름을 직접 쓰지 않고 기본 label을 쓰고 싶을 때가 많을 거예요. 이 경우엔 파일에서 행 이름 열을 빼버리면 됩니다. 아래처럼요.

Input file form without row labels:

Price    Floor     Area   Rooms     Age  Cent.heat
52.00    111.0      830     5       6.2      no
54.75    128.0      710     5       7.5      no
57.50    101.0     1000     5       4.2      no
57.50    131.0      690     6       8.8      no
59.75     93.0      900     5       1.9     yes
...

그러면 데이터 프레임은 이렇게 읽습니다.

> HousePrice <- read.table("houses.data", header=TRUE)

여기서 header=TRUE 옵션은 첫 줄이 제목(헤딩) 줄임을 지정해 주는 건데, 파일 형태를 보면 자연스럽게 "그러니까 명시적인 행 이름은 없다"는 뜻도 함께 전달돼요.

7.2 scan() 함수

데이터 벡터들이 모두 길이가 같고, 서로 병렬로 읽혀야 한다고 가정해 볼게요. 벡터가 세 개 있는데, 첫 번째는 문자형이고 나머지 두 개는 숫자형이고, 파일 이름은 input.dat라고 해보죠. 첫 단계는 scan()으로 세 벡터를 리스트 형태로 읽는 겁니다.

> inp <- scan("input.dat", list("",0,0))

두 번째 인자는 더미 리스트 구조인데, 읽어 들일 세 벡터의 형태(mode)를 정해 주는 역할을 해요. 결과는 inp에 저장되는데, 이건 읽어 들인 세 벡터를 성분으로 갖는 리스트입니다. 데이터 항목을 서로 다른 세 벡터로 분리하려면, 이렇게 할당문을 쓰면 돼요.

> label <- inp[[1]]; x <- inp[[2]]; y <- inp[[3]]

더 편리하게는, 더미 리스트의 성분에 이름을 붙일 수도 있어요. 그렇게 하면 그 이름으로 읽어 들인 벡터에 접근할 수 있습니다. 예를 들어 이렇게요.

> inp <- scan("input.dat", list(id="", x=0, y=0))

변수들을 따로 접근하고 싶으면, 작업 프레임에 다시 할당하거나:

> label <- inp$id; x <- inp$x; y <- inp$y

리스트를 검색 경로(search path)의 위치 2에 attach할 수도 있어요. (이 내용은 Attaching arbitrary lists 절을 참고하세요.)

만약 두 번째 인자가 리스트가 아니라 단일 값이라면, 단일 벡터가 읽힙니다. 이때 모든 성분은 더미 값과 같은 형태여야 해요.

> X <- matrix(scan("light.dat", 0), ncol=5, byrow=TRUE)

이보다 더 정교한 입력 기능들도 있는데, 자세한 내용은 매뉴얼에 나와 있어요.

7.3 내장 데이터셋 접근하기

R에는 약 100개의 데이터셋이 (패키지 datasets에) 딸려 나오고, 그 외에도 (R과 함께 제공되는 권장 패키지를 포함한) 다양한 패키지에서 더 많은 데이터셋을 얻을 수 있어요. 현재 사용 가능한 데이터셋 목록을 보려면 이렇게 입력합니다.

data()

R과 함께 제공되는 데이터셋은 모두 이름만으로 바로 접근 가능해요. 다만 아직도 많은 패키지가 예전 관례, 즉 data를 데이터셋을 R로 불러들이는 데 쓰는 방식을 따르고 있어요. 예를 들어:

data(infert)

이건 표준 패키지에서 여전히 쓸 수 있어요 (위 예시처럼). 대부분의 경우 같은 이름의 R 객체가 불러들여지는데, 몇몇 경우엔 여러 객체가 한꺼번에 로드되기도 하니, 그 객체의 온라인 도움말을 보고 어떤 결과가 나올지 확인해 보세요.

7.3.1 다른 R 패키지에서 데이터 불러오기

특정 패키지의 데이터에 접근하려면 package 인자를 쓰면 됩니다. 예를 들어:

data(package="rpart")
data(Puromycin, package="datasets")

패키지가 library로 attach되어 있다면, 그 패키지의 데이터셋은 자동으로 검색 경로에 포함돼요.

사용자가 기여한 패키지(커뮤니티 패키지)는 데이터셋의 좋은 보고가 되기도 합니다.

7.4 데이터 편집하기

edit를 데이터 프레임이나 행렬에 대해 호출하면, 편집을 위한 별도의 스프레드시트 같은 환경이 열려요. 데이터셋을 읽어 들이고 나서 작은 수정을 할 때 아주 유용하죠. 다음 명령은:

> xnew <- edit(xold)

xold라는 데이터셋을 편집할 수 있게 해 주고, 편집을 마치면 변경된 객체가 xnew에 할당됩니다. 원래 데이터셋 xold 자체를 바꾸고 싶다면, 가장 간단한 방법은 fix(xold)를 쓰는 거예요. 이건 xold <- edit(xold)와 동일한 동작을 합니다.

새 데이터를 스프레드시트 인터페이스로 입력하고 싶다면:

> xnew <- edit(data.frame())

이렇게 하면 됩니다.

더 알아보기

  • R로 데이터를 가져오고 내보내는 전 과정을 더 깊이 다루는 공식 문서: R Data Import/Export
  • 데이터셋 목록과 각 객체의 세부 내용은 R 세션에서 data(), data(package="패키지명"), 그리고 객체별 온라인 도움말(?객체명)로 확인할 수 있어요.
  • 검색 경로에 리스트나 데이터 프레임을 올려 이름으로 바로 접근하는 attach() 개념은 "Attaching arbitrary lists" 절에서 이어서 다룹니다.