20
R 데이타 조작 R 프로그래밍 기초 #2 2014.11.19 조대협 http://bcho.tistory.com

R 프로그래밍-향상된 데이타 조작

Embed Size (px)

DESCRIPTION

R 프로그래밍 향상된 데이타 조작 apply 함수, doBy 패키지,데이타 정렬,분할,합치기,부분 집합등

Citation preview

Page 1: R 프로그래밍-향상된 데이타 조작

R 데이타 조작

R 프로그래밍 기초 #2

2014.11.19 조대협 http://bcho.tistory.com

Page 2: R 프로그래밍-향상된 데이타 조작

아이리스 데이타

• R에는 데이타 분석이나 기계학습 관련한 샘플 데이타가 많이 들어 있다.

• 아이리스(붓꽃) 데이타는 통계학셔 Fisher가 소개한 데이타로 붓꽃의 3가지 종에 대해서 꽂받침(sepal),꽂잎(petal)의 길이를 정리 한 데이타

※ 종별로 50, 총 150개의 데이타가 저장됨

컬럼명 의미

Species 종류 (setosa,vesicolor,virginica)

Sepal.Width 꽃받침의 너비

Sepal.Length 꽃받침의 길이

Petal.Width 꽃잎의 너비

Petal.Length 꽃잎의 길이

• library(help=dataset) 하면 미리 준비된 샘플 데이타 셋을 볼 수 있음

• http://archive.ics.uci.edu/ml 을 보면 UC 어바인 대학의 기계학습 repository에서 추가 데이타를 얻을 수 있음

Page 3: R 프로그래밍-향상된 데이타 조작

파일 입출력

• CSV 파일에서 읽고 쓰기

x<-data.frame(id=c(1,2,3),name=c('terry','cath','stella'),score=c(96,99,80));

#파일에 쓴다write.csv(x,'d.csv',row.names=FALSE) # d.csv 파일에 쓴다. row.names=FALSE이기 때문에, 행라벨(행번호)는 생략된다.

getwd(); # 현재 working directory 리턴dir('.'); # 지정 디렉토리의 파일 목록 리턴

#파일에서 읽기y<-read.csv('d.csv');

y;

str(y); # 그냥 읽으면 문자열이 factor (cf.enumeration)으로 읽힌다.

y<-read.csv('d.csv',stringsAsFactors=FALSE); # 문자열을 Factor가 아니라 문자열로 읽이 위함

str(y);

Page 4: R 프로그래밍-향상된 데이타 조작

파일 입출력

• 객체의 파일 입출력– 객체를 바이너리 형태로 파일에 저장한다. 계산중 중간값, 결과, 모델등을 저장할때 유용하게 사용할 수 있음

– 함수나 클래스도 저장이 가능할까?

x<-data.frame(id=c(1,2,3),name=c('terry','cath','stella'),score=c(96,99,80));

save(x,file='x.data'); # x 객체를 바이너리 형태로 파일에 저장한다. 계산 중간값,결과,모델등을 저장할때 유용하게 사용될 수 있다.

rm(list=ls())

load('x.data') #다시 x 객체를 파일에서 읽어드린다. (x 변수로 그대로 읽힌다.)

Page 5: R 프로그래밍-향상된 데이타 조작

데이타 프레임의 행,컬럼 합치기

• rbind(..) 지정한 데이타들을 행으로 취급하여 합친다.

• cbind(..) 지정한 데이타들을 열로 취급하여 합친다

rm(list=ls())

x<-data.frame(id=c(1,2,3),name=c('terry','cath','stella'),score=c(96,99,80));

str(x) # 이렇게 하면 두번째 컬럼이 Factor가 된다.

y<-rbind(x,c(4,'yuna',80)); # 이렇게 하면 에러가 난다. 두번째 컬럼이 현재는 Factor형이기 때문에

x$name<-as.character(x$name); # 두번째 열을 문자열로 바꾼후

str(x)

y<-rbind(x,c(4,'yuna',80)); # 다시 row를 추가하면

y; #정상적으로 들어감을 볼 수 있다.

# 다음은 열을 추가하는 cbind

z<-cbind(x,city=c('seoul','sf','tokyo'))

str(z) # 이렇게 하면 새로 추가한 열을 또 factor 형이 된다.

z<-cbind(x,city=c('seoul','sf','tokyo'),stringsAsFactors=F)

str(z) # 이렇게 하면 새로 추가한 열은 문자열로 된다.

Page 6: R 프로그래밍-향상된 데이타 조작

apply 계열 함수

• 벡터,행렬 또는 데이타 프레임의 데이타에 임의의 함수를 적용하여 값을 얻기 위한 함수

• for등으로 루프를 도는 것보다 성능이 빠름 (테스트 해볼 필요 있음)

함수명 의미 입력 출력

apply 행렬이나 배열에 함수를 적용행방향이나 열방향으로 적용

행렬이나 배열과 같은 다차원 데이타 벡터,배열,리스트

lapply 벡터,리스트,표현식 리스트

sapply 벡터,리스트,표현식 벡터,행렬,배열

tapply 벡터에 있는 데이타를 특정 기준에따라 그룹으로 묶은 후 각 그룹마다주언진 함수를 적용하고 반환

mapply sapply의 확장 버전으로, 여러개의벡터 또는 리스트를 인자로 받아서, 함수에 각 데이타의 첫째,둘째,셋째요소들을 반영한후 결과를 반환

여러개의 벡터, 여러개의 리스트

※ vapply

Page 7: R 프로그래밍-향상된 데이타 조작

apply 계열 함수

• apply : 행방향(1:가로), 열방향(2:세로)으로 함수 적용

• rowMeans,rowSums,colSums,colMeans와 같이 자주 쓰는 행&열간 계산 함수는 미리 정의됨

> # matrix에 적용> rm(list=ls())> d<-matrix(1:9,ncol=3)> str(d)int [1:3, 1:3] 1 2 3 4 5 6 7 8 9

> d[,1] [,2] [,3]

[1,] 1 4 7[2,] 2 5 8[3,] 3 6 9> apply(d,1,sum)[1] 12 15 18> apply(d,2,sum)[1] 6 15 24>

> # array에 적용> a<-array(1:12,dim=c(3,2,2))> str(a)int [1:3, 1:2, 1:2] 1 2 3 4 5 6 7 8 9 10 ...

> a, , 1

[,1] [,2][1,] 1 4[2,] 2 5[3,] 3 6

, , 2

[,1] [,2][1,] 7 10[2,] 8 11[3,] 9 12

> apply(a,1,sum)[1] 22 26 30> apply(a,2,sum)[1] 30 48> # 참고: 행의 합과, 열의 합은 많이 사용되서colSums,colMeans, rowSums,rowMeans 로 미리 함수가 정해져있음> rowSums(a)[1] 22 26 30> rowMeans(a)[1] 5.5 6.5 7.5

Page 8: R 프로그래밍-향상된 데이타 조작

apply 계열 함수

• lapply : 벡터,리스트,표현식에 함수 적용 후, 리스트형 (K/V)로 반환

• unlist : 리스트형을 벧터로 반환 (리스트내의 이름값 보관 여부를 결정 가능)> # lapply (리스트를 반환한다.), R에서 리스트는 Hash와 같이Key/Value의 개념이고,Key를 정의안하면, Key는 [[1]],[[2]]식으로인덱스로 지정된다.> # 참고 리스트를 벡터로 변환할때는 unlist를 사용하면 된다.> result<-lapply(c(1:3),function(x){x*2})> result[[1]][1] 2

[[2]][1] 4

[[3]][1] 6

> str(result) # 리스트형으로 반환됨을 볼 수 있음List of 3$ : num 2$ : num 4$ : num 6

> uresult<-unlist(result)> str(uresult)num [1:3] 2 4 6

> > x<-list(a=2:100,b=1:3)> lapply(x,mean)$a[1] 51

$b[1] 2

> ux<-unlist(lapply(x,mean)) # 그냥unlist하면 이름이 보관된다./> uxa b 이름값이 그대로 보관됨51 2 > str(ux)Named num [1:2] 51 2- attr(*, "names")= chr [1:2] "a" "b"

> ux[1] # 리턴값이 1행:a, 2행:51로 첫행에 컬럼명으로 list key가 저장된다.a

51 > ux2<-unlist(lapply(x,mean),use.names=F)> ux2 # 첫행에서 컬럼명을 빼버린다.[1] 51 2>

Page 9: R 프로그래밍-향상된 데이타 조작

apply 계열 함수

• lapply

> d=as.list(colMeans(iris[,1:4])) > d$Sepal.Length[1] 5.843333

$Sepal.Width[1] 3.057333

$Petal.Length[1] 3.758

$Petal.Width[1] 1.199333

> df <- as.data.frame(d,nrow=1,byrow=T)> dfSepal.Length Sepal.Width Petal.Length Petal.Width

1 5.843333 3.057333 3.758 1.199333> View(df)>

> #또는> d=lapply(iris[,1:4],mean)> d$Sepal.Length[1] 5.843333

$Sepal.Width[1] 3.057333

$Petal.Length[1] 3.758

$Petal.Width[1] 1.199333

> df <- as.data.frame(d,nrow=1,byrow=T)> dfSepal.Length Sepal.Width Petal.Length Petal.Width

1 5.843333 3.057333 3.758 1.199333> # d=as.list를 안하거나, d=lapply를 안하면, 리턴값이 벡터로 와서, dataframe에서 행/열이 바뀌어 버림. 이걸 다시 바꿀려면 전치행렬 t(x0하면됨)>

d<-colMeans(iris[,1:4])

Page 10: R 프로그래밍-향상된 데이타 조작

apply 계열 함수

• sapply : lapply와 유사 (함수를 적용), 대신 리턴이 벡터 또는 행렬,배열

> #> # sapply> # lapply와 input은 같지만 리턴은 vector,matrix,array (즉 행렬행으로 리턴)> rm(list=ls())> x<-sapply(iris[,1:4],mean)> str(x)Named num [1:4] 5.84 3.06 3.76 1.2- attr(*, "names")= chr [1:4] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width"

> xSepal.Length Sepal.Width Petal.Length Petal.Width

5.843333 3.057333 3.758000 1.199333 > xf=as.data.frame(t(x))> xfSepal.Length Sepal.Width Petal.Length Petal.Width

1 5.843333 3.057333 3.758 1.199333> View(xf)>

Page 11: R 프로그래밍-향상된 데이타 조작

apply 계열 함수

• tapply : 주어진 데이타를 그룹으로 묶은 뒤 그룹에 각 함수를 적용– 그룹으로 묶을때, Index (색인)으로 묶음 이 색인은 팩터로 지정해야 하며, 팩터가 아니면 팩터로 형변환됨

– tapply(벡터,색인,함수,함수에 넘기는 추가인자들…)

> ###> # tapply> # 그룹별로 함수를 적용할 수 있음> # 그룹은 색인을 정의해서 그 단위별로 그룹핑 함> index<-c(1:10%%2)> tapply(1:10,index,sum) # tappy(1:10,c(1 0 1 0 1 0 1 0 1 0),sum)과 동일, 1,0 두개의 그룹이 있고, 첫번째 값은 1 로 분류,두번째 값은 2로0 1

30 25 > # 분류한꼴

첫번째는 팩터1,두번째는 팩터0,세번째는 팩터1,…> tapply(1:4,list(c(1,2,3,4),c(5,6,7,8)) ,sum)

5 6 7 81 1 NA NA NA2 NA 2 NA NA3 NA NA 3 NA4 NA NA NA 4

x의 첫번째 데이타는 (1,5) 팩터, 두번째는 (2,6), 세번째는 (3,7) 팩터로 분리됨

Page 12: R 프로그래밍-향상된 데이타 조작

apply 계열 함수

• mapply: 함수에 리스트 또는 벡터로 주어진 인자를 적용한 결과를 반환한다.

> # mapply> # sapply와 비슷하지만 함수에 여러개의 인자를 동시에 올릴 수 있다.> mapply(sum,c(1:10),c(21,30),c(31,40)) # sum(1+21+31), sum(2+22+32),... sum(10+30+40) 과 동일[1] 53 72 55 74 57 76 59 78 61 80

>

Page 13: R 프로그래밍-향상된 데이타 조작

데이타를 그룹으로 묶은 후 함수 호출하기

• doBy : 그룹별로 함수를 호출하기 위한 확장 패키지

– summaryBy : 데이타 프레임을 컬럼으로 묶은 후, 요약값 계산

– orderBy : 지정된 컬럼에 따라서 데이타 프레임 정렬

– sampleBy : 데이타 프레임에서 특정 컬럼 값에 따라 데이타를 묶은 후, 각 그룹에서 샘플(표본) 추출

• 포뮬러 (심화 토론 필요)

– Y1+Y2+….+Yn ~ X1+X2+…+Xn : Yn의 순서쌍을 Xn으로 모델링 한다.

– 선형 회귀에서 Y~X는 Y=a*X1+b와 같은 의미

컬럼명 의미

Y~X1+X2 Y를 X1과 X2로 모델링

Y~X1-X2 Y를 X1으로 모델링 하되 X2는 제외한다※선형회귀에서 Y~X1+X2-1은 Y=aX1+bX2로 상수항 c를제외한다는 의미를 갖는다

Y~X1|X2 X2의 값에 따라 데이타를 묶은 후 Y~X1 을 적용

Y~X1:X2 Y를 X1과 X2의 상호작용에 따라 모델링 한다. 상호 작용은Y=aX1*X2와 같이 X1과 X2가 동시에 Y에 영향을 주는 경우이다.

Y~X1*X2 Y~X1+X2+X1:X2의 축약형

Page 14: R 프로그래밍-향상된 데이타 조작

데이타를 그룹으로 묶은 후 함수 호출하기

• summaryBy

> summary(iris)Sepal.Length Sepal.Width Petal.LengthMin. :4.300 Min. :2.000 Min. :1.000 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 Median :5.800 Median :3.000 Median :4.350 Mean :5.843 Mean :3.057 Mean :3.758 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 Max. :7.900 Max. :4.400 Max. :6.900 Petal.Width Species Min. :0.100 setosa :50 1st Qu.:0.300 versicolor:50 Median :1.300 virginica :50 Mean :1.199 3rd Qu.:1.800 Max. :2.500

> library(doBy)> summaryBy(Sepal.Width+Sepal.Length~Species,iris)

Species Sepal.Width.mean Sepal.Length.mean1 setosa 3.428 5.0062 versicolor 2.770 5.9363 virginica 2.974 6.588> # Species에 따른 Width와 Length의 평균값

> sample(1:10,5)[1] 7 9 10 4 1> sample(1:10,5,replace=T)[1] 4 3 5 6 8> sample(1:10,5,replace=T)[1] 6 7 2 1 10> sample(1:10,5,replace=T)[1] 9 5 10 7 4> sample(1:10,5,replace=T) #복원 추출[1] 7 8 6 7 5

• sample : 표본 추출(복원/비복원 추출 지원, 가중치 지원)

• sampleBy : 표본 추출

– 포뮬러 사용, 복원/비복원 지원,

– 계통 추출 지원(?:질문),추출할 샘플 비율 지원> sampleBy(~Species,frac=0.1,data=iris)

Sepal.Length Sepal.Width Petal.Length Petal.Width Speciessetosa.13 4.8 3.0 1.4 0.1 setosasetosa.18 5.1 3.5 1.4 0.3 setosasetosa.31 4.8 3.1 1.6 0.2 setosasetosa.41 5.0 3.5 1.3 0.3 setosasetosa.42 4.5 2.3 1.3 0.3 setosaversicolor.54 5.5 2.3 4.0 1.3 versicolorversicolor.56 5.7 2.8 4.5 1.3 versicolorversicolor.76 6.6 3.0 4.4 1.4 versicolorversicolor.78 6.7 3.0 5.0 1.7 versicolorversicolor.88 6.3 2.3 4.4 1.3 versicolorvirginica.101 6.3 3.3 6.0 2.5 virginicavirginica.120 6.0 2.2 5.0 1.5 virginicavirginica.122 5.6 2.8 4.9 2.0 virginicavirginica.134 6.3 2.8 5.1 1.5 virginica

Species별로 10%씩(5개) 표본 추출

Page 15: R 프로그래밍-향상된 데이타 조작

데이타를 그룹으로 묶은 후 함수 호출하기

• orderBy : 특정 필드에 따라 정렬

> head(orderBy(~Sepal.Width,iris))Sepal.Length Sepal.Width Petal.Length Petal.Width Species

61 5.0 2.0 3.5 1.0 versicolor63 6.0 2.2 4.0 1.0 versicolor69 6.2 2.2 4.5 1.5 versicolor120 6.0 2.2 5.0 1.5 virginica42 4.5 2.3 1.3 0.3 setosa54 5.5 2.3 4.0 1.3 versicolor

> head(orderBy(~Sepal.Length+Sepal.Width,iris)) # ~오른쪽에 있는 Sepal.Length와 Sepal.Width 순에 따라서 정렬한다.

Sepal.Length Sepal.Width Petal.Length Petal.Width Species14 4.3 3.0 1.1 0.1 setosa9 4.4 2.9 1.4 0.2 setosa39 4.4 3.0 1.3 0.2 setosa43 4.4 3.2 1.3 0.2 setosa42 4.5 2.3 1.3 0.3 setosa4 4.6 3.1 1.5 0.2 setosa

> head(order(iris$Sepal.Width))[1] 61 63 69 120 42 54> iris$Sepal.Width[order(iris$Sepal.Width)][1] 2.0 2.2 2.2 2.2 2.3 2.3 2.3 2.3 2.4 2.4 2.4 2.5 2.5 2.5[15] 2.5 2.5 2.5 2.5 2.5 2.6 2.6 2.6 2.6 2.6 2.7 2.7 2.7 2.7[29] 2.7 2.7 2.7 2.7 2.7 2.8 2.8 2.8 2.8 2.8 2.8 2.8 2.8 2.8[43] 2.8 2.8 2.8 2.8 2.8 2.9 2.9 2.9 2.9 2.9 2.9 2.9 2.9 2.9[57] 2.9 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0[71] 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.0 3.1[85] 3.1 3.1 3.1 3.1 3.1 3.1 3.1 3.1 3.1 3.1 3.2 3.2 3.2 3.2[99] 3.2 3.2 3.2 3.2 3.2 3.2 3.2 3.2 3.2 3.3 3.3 3.3 3.3 3.3

[113] 3.3 3.4 3.4 3.4 3.4 3.4 3.4 3.4 3.4 3.4 3.4 3.4 3.4 3.5[127] 3.5 3.5 3.5 3.5 3.5 3.6 3.6 3.6 3.6 3.7 3.7 3.7 3.8 3.8[141] 3.8 3.8 3.8 3.8 3.9 3.9 4.0 4.1 4.2 4.4

• order : 데이타를 정렬한 후, 색인(Index)를 반환(데이타를 반환하지 않음)

Page 16: R 프로그래밍-향상된 데이타 조작

데이타 분리 및 병합

• split : 조건에 따라 데이타 분리 (group by)

• subset : 조건에 따른 부분 집합 (where)

• merge : 데이타를 공통된 값에 기준해 병합 (토론 : rbind,cbind과 차이는?)> split(iris,iris$Species) # Species에 따라 데이타를 분할 일종의 group by?$setosa

Sepal.Length Sepal.Width Petal.Length Petal.Width Species1 5.1 3.5 1.4 0.2 setosa2 4.9 3.0 1.4 0.2 setosa

$versicolorSepal.Length Sepal.Width Petal.Length Petal.Width Species

51 7.0 3.2 4.7 1.4 versicolor52 6.4 3.2 4.5 1.5 versicolor

$virginicaSepal.Length Sepal.Width Petal.Length Petal.Width Species

101 6.3 3.3 6.0 2.5 virginica102 5.8 2.7 5.1 1.9 virginica

> head(subset(iris,Species=='virginica')) # split는 전체를 출력하지만 이건 조건에 맞는 것만 출력. 일종의 whereSepal.Length Sepal.Width Petal.Length Petal.Width Species

101 6.3 3.3 6.0 2.5 virginica102 5.8 2.7 5.1 1.9 virginica103 7.1 3.0 5.9 2.1 virginica> head(subset(iris,Species=='virginica',select="Sepal.Width")) # select는 특정 필드만 출력

Sepal.Width101 3.3102 2.7103 3.0104 2.9105 3.0106 3.0>

Page 17: R 프로그래밍-향상된 데이타 조작

데이타 분리 및 병합

• merge

> x<-data.frame(name=c('a','b','c'),math=c(1,2,3))> y<-data.frame(name=c('a','c','b'),math=c(4,5,6))> merge(x,y)[1] name math<0 행> <또는 row.names의 길이가 0입니다>> x<-data.frame(name=c('a','b','c'),math=c(1,2,3))> y<-data.frame(name=c('a','c','b'),english=c(4,5,6))> merge(x,y)name math english

1 a 1 42 b 2 63 c 3 5

Page 18: R 프로그래밍-향상된 데이타 조작

데이타 정렬과 조건에 맞는 색인 찾기

• sort : 정렬한 값을 리턴

• order : 정렬한 값의 색인(index)를 리턴

• which(x) : 조건이 참인 색인을 반환

• which.max(x) : 최대값의 색인을 반환

• which.min(x) : 최소값의 색인을 반환

> which(iris$Species=='setosa')[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

[41] 41 42 43 44 45 46 47 48 49 50

Page 19: R 프로그래밍-향상된 데이타 조작

데이타 프레임내의 데이타 접근

• with() : 코드 블록 안에서 데이타 프레임 명을 생략하고 접근 (읽기만 가능)

• within() : 코드 블록 안에서 데이타 프레임 명을 생략하고 읽기/쓰기 접근

※ 주의 : 업데이트된 데이타 프레임은 원래 데이타 프레임에 반영되지 않음

• attach() : 코드블록 밖에서도 선언 후, 데이타 프레임명을 생략하고 접근

• detach() : 데이타 프레임명을 생략하고 접근하는 것을 종료

Page 20: R 프로그래밍-향상된 데이타 조작

그룹별 연산

• doBy : 데이타를 그룹별로 나눈 후 특정 계산을 적용 (summary,sample 표본 추출등)

• aggregate는 일반적인 함수에 사용 (즉 그룹에 적용될 함수를 정의할 수 있음)

> aggregate(Sepal.Width~Species,iris,mean)Species Sepal.Width

1 setosa 3.4282 versicolor 2.7703 virginica 2.974

# Species로 그룹핑을 한후, Sepal.Width에 대한 각각의 mean 값을 구함