(R) 6장 팩터와 레벨

R팩터는 간단하게 벡터에 추가 정보가 더해진 것으로 보면된다.
추가정보는 벡터의 값 가운데 겹치지 않는 값의 기록으로 이뤄져 있고, 이를 '레벨level'이라고 한다.

예)
x<-c(5,12,13,12)
xf<-factor(x)
xf는
[1] 5 12 13 12
Levels: 5 12 13


*팩터의 길이는 레벨의 수가 아닌 데이터의 길이로 정의된다.
*다음처럼 세 레벨을 추가할 수 있다.

x<-c(5,12,13,12)
xff<-factor(x,levels=c(5,12,13,88))
xff는
[1] 5 12 13 12
Levels: 5 12 13 88


>xff[2]<-88
>xff
[1] 5 88 13 12
Levels: 5 12 13 88


만약 레벨에 없는 겂 xff[2]<-28을 하게되면 에러가 발생한다.

6.2 팩터에 사용되는 일반적인 함수


6.2.1 tapply()함수

tapply()는 임시로 x를 팩터의 각 레벨(혹은 팩터가 여러 개일 경우 팩터의 레벨 간의 조합)에 대응되는 그룹별로 나눈 후 이에 따른 x의 부분 벡터에 g()를 적용한다.

>ages<-c(25,26,55,37,21,42)
>affils<-c("R","D","D","R","U","D")
>tapply(ages,affils,mean)

D    R    U
41  31   21


만약 팩터가 2개이상이면 어떻게 될까?
그럼 각 팩터는 앞의 예제처럼 각 그룹을 만들고, 각 그룹 간에 AND연산이 일어난다. 예를들어 성별, 나이, 수입에 대한 변수를 포함하는 데이터 세트에 tapply(x,f,g)에서 x는 수입, f는 성별과 해당 사람이 25살을 기준으로 아래인지 위인지가 표기된 두 개의 팩터가 될 것이다.


d<-data.frame(list(gender=c("M","M","F","M","F","F"),age=c(47,59,21,32,33,24),income=c(55000,88000,32450,76500,123000,45650)))


d$over25<-ifelse(d$age>25,1,0)
tapply(d$income,list(d$gender,d$over25),mean)




여기서는 성별과 25살 이상인지 여부에 대한 구분자인 두 팩터를 명시했다.
각 팩터는 두 개의 레벨을 가지므로, tapply()는 수입 데이터를 성별과 나이의 조합인 4개의 그룹으로 나누고 각 그룹에 대해 mean()을 적용했다.

6.2.2 split() 함수

간단한 형태인 split(x,f)에서 x는 데이터 프레임이나 벡터이고 f는 패터 혹은 팩터의 리스트이다. x를 그룹별로 나눠서 리스트를 반환해 주는 기능을 한다.
이때 split()의 x에서는 데이터프레임이 쓰일 수 있지만 tapply()에서는 안됨을 기억하자.





이 결과 암컷의 경우 2,3,7번째, 새끼 전복은 4번째, 수컷은 1,5,6번째 기록에 들어있다는 것을 알려준다.


6.2.3 by()함수


전복 데이터 예제에서 수컷, 암컷, 새끼 전복의 각 성별을 구분해 길이 대비 지름으로 회귀분석을 하려고 했다고 하자. 처음 보기에는 tapply()를 이용해 각각에 맞게 무언가를 할 수 있을 것 같지만, 함수의 첫번째 인수에는 데이터 프레임이나 행렬이 아닌 벡터가 들어가야 한다는 벽에 부딪힌다. 사용되는 함수는 range()와 같이 다변량 함수일 수 있지만, 입력 값은 벡터이어야 한다. 
하지만 회귀분석을 위한 입력값은 예측될 값과 예측 변수로 이뤄진 최소 두 개의 열을 가진 행렬(이나 데이터 프레임)이어야 한다. 
전복 데이터의 경우에는 행렬은 지름과 길이 열로 이뤄져 있다.


by()는 여기서 사용된다. tapply()와 비슷하지만 벡터대신 객체를 사용한다.



6.3 테이블 사용하기

6.3.1 테이블로 행렬, 배열 연산하기

대부분 수학적 용도가 아닌 행렬,배열 연산이 데이터프레임에서 사용될 수 있듯이, 테이블에도 동일하게 적용할 수 있다.
하지만 R에서는 중간핪을 계산해 주는 addmargins()라는 함수를 제공해 준다.
다음 예제를 보자.




각 차원 및 레벨의 이름은 다음과 같이 dimnames()로 찾을 수 있다.
>dimnames(cttab)
$Vote.for.X
[1] "No" "Not Sure" "Yes"



만약 Not Sure라는 항목을 제외한 테이블을 보여주고 싶을 때는
subtable()이란 함수를 사용하여 부분 테이블 추출을 할 수 있다.
두 인수가 필요하다.
  • tbl: table클래스를 갖는 사용하고자 하는 테이블
  • subnames: 부분 테이블 추출 시에 사용하고자 하는 리스트, tbl의 각 차원을 이름으로 하는 리스트의 각 구성요소에는 필요한 레벨의 이름이 들어간다.

subtable(cttab,list(Vote.for.X=c("No","Yes"),Voted.for.X.Last.Time=c("No","Yes")))



6.3.3 테이블에서 가장 큰 셀 찾기


행이나 차원이 매우 큰 테이블을 보는 것은 어려운 일이다. 이 경우 가장 많이 나타나는 셀들에 초점을 맞추는 것이 하나의 방법이다. 
이때, tabdm()함수를 사용한다.

tabdom(tbl,k)
-->tbl테이블에서 k개의 높은 빈도의 셀을 알려준다.

tabdom<-function(tbl,k){
  #Freq 열을 추가해 tbl을 나타내는 데이터 프레임을생성한다.
  tbldf<-as.data.frame(tbl)
  freqord<-order(tbldf$Freq,decreasing = TRUE)
  #이 순서대로 데이터 프레임을 재배열한 후 위의 k행을 가져온다.
  dom<-tbldf[freqord,][1:k,]
}




6.4 그 밖의 팩터 및 테이블 관련 함수


6.4.1 aggregate() 함수

aggregate()함수는 그룹의 각 변수별로 tapply()를 한번씩 호출한다.
# aggregate(계산될칼럼~기준칼럼, 데이터, 함수)


예를들어, 다음 전복데이터는 성별로 나뉜 각 변수 별 중간값을 다음과 같이 구할 수 있다.

첫 번째 인수인 aba[ ,-1]은 첫 번째 열인 Gender를 제외한 전체 데이터 프레임이다. 두 번쨰 인수인 Gender 팩터로 리스트 형이다. 마지막으로 세 번째 인수는 R이 팩터별로 부분그룹으로 나눠진 각 데이터 프레임에 대해서 각 열의 중간값을 계산하라고 알려주는 역할을 한다.



6.4.2 cut() 함수

테이블을 위해 팩터를 생성하는 일반적인 방법은 cut()함수를 사용하는 것이다.
데이터 벡터 x와 벡터 b에 의해 정의된 데이터 집합들을 넣어준다.
그러면 각 집합이 x의 원소 중 어디에 속하게 되는지를 알려준다.





댓글

이 블로그의 인기 게시물

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬

(18장) WebSocekt과 STOMP를 사용하여 메시징하기