(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))


댓글

댓글 쓰기

이 블로그의 인기 게시물

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

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

(ElasticSearch) 결과에서 순서 정렬