(R) plyr패키지 (ddply, adply)
1. adply 함수
adply()는 배열(a)을 받아 데이터 프레임(d)을 반환하는 함수다. 그러나 입력이 받으시 배열일 필요는 없다. 그보다는 주어진 입력을 숫자 색인으로 읽을 수 있는가(즉, 행렬처럼 다룰 수 있는 형태의 데이터인가)하는 점이 중요하다.
plyr::adply(
.data, #행렬,배열 또는 데이터프레임
#함수를 적용할 방향. 1(행 방향), 2(컬럼 방향) 또는 c(1,2)(행과 컬럼 모두의 방향)
.margins,
.fun=NULL #.margin방향으로 잘려진 데이터에 적용할 함수
)
반환값은 데이터 프레임이다.
adply()함수는 apply()함수와 유사하지만, apply()는 행 방향으로 처리할 때 각 컬럼에 서로 다른 데이터 타입이 섞여 있다면 예상치 못한 타입 변환이 발생할 수 있다.
apply()에 숫자형 컬럼만 입력으로 주어졌을 경우는 그 값이 제대로 숫자로 나오지만, 문자열이 섞이면 데이터가 모두 문자열로 변환된다.
반면 adply()를 사용해 결과를 데이터 프레임을 변환하면 결과 타입이 문자열로 모두 바뀌는 현상을 피할 수 있다.
예)
>adply(iris,1,function(row){row$Sepal.Length>=5.0 & row$Species=="setosa"})
2. ddply 함수
데이터 프레임을 분할하고 함수를 적용한 뒤 결과를 데이터 프레임으로 반환한다.
plyr::ddply(
.data,
.variables, #데이터를 그룹 지을 변수명
.fun=NULL
)
adply()와 ddply()의 가장 큰 차이점이라면 adply()는 행 또는 칼럼 단위로 함수를 적용하는 반면 ddply()는 .variables에 나열한 칼럼에 따라 데이터를 나눈 뒤 함수를 적용한다는 점이다.
ab.test.imp.summary<-ddply(ab.test.imp,.(log_date,test_case),summarize,imp=length(user_id),
cv=sum(is.goal),cvr=sum(is.goal)/length(user_id))
이 기능은 log_date와 test_case 두 변수의 단위로 세 번의 집계를 실시하고있다. 첫번쨰는 imp라는 항목에 user_id수를 카운트해서 집어넣은 것이고, 두번째는 cv라는 변수에 is.goal수의 합계를 집어넣은 것이다. 마지막으로 세 번째는 cvr항목에 이 두수치를 나눈 비율을 넣은 것이다.
즉, 그날 배너광고가 얼마나 표시되었고, 몇 명이 클릭했으며, 클릭률은 어떤지 집계한 것이다.
다음으로 'summarize'대신에 transform을 지정했는데, 이것으로 집계한 결과를 원래 데이터에 추가할 수 있습니다.
여기서는 test_case별 클릭률을 원래 데이터에 추가하고 있습니다.
ab.test.imp.summary<-ddply(ab.test.imp.summary,.(test_case),transform,cvr.avg=sum(cv)/sum(imp))
*그룹마다 연산을 쉽게 수행하기
plyr의 예에서는 adply() 또는 ddply()에 임의의 사용자 정의 함수를 넘겨 주어 분석을 수행했다.
그러나 공통적으로 자주 사용하는 유형의 계산은 transform(), mutate(), summarise(), subset()을 사용하면 더 간단히 표현할 수 있다.
1. 객체(예를들면, 데이터프레임)를 변환한다.
base::transform(
_data #변환할 객체
... #태그=값 형태의 인자들
)
----> 데이터 프레임 _data에 ...에 지정한 연산을 수행한 뒤 그 결과를 저장한 새로운 칼럼을 추가한 데이터 프레임을 반환한다.
2. 데이터 프레임에 새로운 칼럼을 추가하거나 기존 컬럼을 수정한다.
plyr::mutate(
.data, #변환할 데이터 프레임
.... # 새로운 칼럼 정의. 컬럼명= 값 형식
)
---->반환 값은 변환된 결과다. 변환이 이루어진다는 점은 transform()과 같지만 컬럼명=값 형태로 지정된 연산이 여러 개 있을 때 앞서의 연산 결과를 뒤에 나오는 연산에서 참조할 수 있다는 차이가 있다.
3. 데이터 프레임을 요약한다.
plyr::summarise(
.data #요약할 데이터 프레임
... #변수=값 형태의 인자들
)
--->...에 지정된 그룹마다의 요약을 수행한 뒤 그 결과를 저장한 새로운 컬럼이 추가된 데이터 프레임을 반환한다.
4. 벡터, 행렬, 데이터프레임의 일부를 반환한다.
subset(
x, #일부를 취할 데이터
subset, #데이터를 선택할지 여부를 지정한 논릿값 벡터
select #선택할 칼럼의 벡터. 제외할 컬럼은 -를 붙여 표시함
)
*transform()
baseball데이터에 각 행이 선수의 몇 년차 통계인지를 뜻하는 cyear컬럼을 추가해보자.
다음 코드는 데이터를 선수 id로 분할하여 그룹 지은 뒤, 각 그룹에서 year의 최솟값과 현재 행의 year값의 차이를 cyear에 저장한다.
>ddply(baseball, .(id), transform, cyear=year-min(year)+1)
*mutate()
transform()을 개선한 함수로, 여러 칼럼을데이터 프레임에 추가할 때 바로 앞서 추가한 칼럼을 뒤에 추가하는 컬럼에서 참조할 수 있어 편리하다.
cyear을 계산한 뒤 log(cyear)를 log_cyear컬럼으로 추가한다. 만약 이를 transform()으로하면 에러가 발생한다.
>ddply(baseball, .(id), mutate, cyear=year-min(year)+1, log_cyear=log(cyear))
*summarise()
transform()이 인자로 주어진 계산 결과를 새로운 컬럼에 추가한 데이터 프레임을 반환하는 반면, summarise()는 계산 결과만을 담은 새로운 데이터 프레임을 반환한다.
baseball데이터에서 각 선수의 최초 데이터가 몇 년도인지를 조사해보자.
데이터를 id마다 그룹 지은 뒤 각 그룹마다 year의 최솟값을 계산한 minyear칼럼을 생성했다. 연산 시 사용할 함수로 summarise()를 지정했으므로 그룹을 짓는 변수인 id와 각 그룹의 요약 값 minyear만 저장된 데이터프레임이다.
>ddply(baseball, .(id), summarise, minyear=min(year))
*subset()
subset()에 조건을 지정하면 그룹별로 조건을 만족하는 행만 추출된다.
다음은 각 선수별로 가장 많은 수의 게임을 플레이한 해의 기록을 찾는 예이다.
baseball을 id 별로 그룹 지은 뒤 가장 많은 게임의 수를 max(g)로 구하고 현재 행의 게임수가 max(g)와 같은 행만 subset()으로 선택했다.
>ddply(baseball, .(id), subset, g==max(g))
블로그 관리자가 댓글을 삭제했습니다.
답글삭제