티스토리 뷰

반응형

데이터 그룹 연산을 위한 주요 함수 정리



1. apply 계열 적용 함수


1. apply(matrix, margin, function, ...) : '행/열별' 함수에 반복적 적용(연산)의 위해 사용 => 그룹함수 연산

  - 2차원 구조 적용 가능, 벡터에 적용 불가  

  - 행별, 열별 연산을 위해 만들어짐 

  - 그룹함수의 적용과 함께 사용 가능

  - 행/열별 "벡터"로 묶어서 함수에 전달하므로 함수는 하나의 인자를 가져야 함


> m1 <- matrix(1:9, ncol = 3)

> apply(m1,1,sum) # 행별 sum

[1] 12 15 18

> apply(m1,2,sum) # 열별 sum

[1]  6 15 24



2. lapply(list, function) : '원소별' 함수에 반복적 적용(연산)을 위해 사용 (리스트로 리턴)

  - 리스트와 데이터 프레임(key를 갖는 구조)은 key별로 연산되기도 함


> f1 <- function(x) {

     strsplit(x,'/')[[1]][1]  # 문자열 분리(리스트로 출력되므로 색인을 통해 원하는 데이터만 추출)  

   }

> v1 <- c('a/b','aa/bb','aaa/bbb')

> lapply(v1,f1)           # f1(v1) 은 원소별 반복 적용 불가(strsplit 자체가 벡터연산 불가)

[[1]]

[1] "a"


[[2]]

[1] "aa"


[[3]]

[1] "aaa"



3. sapply(list, function) : '원소별' 함수에 반복적 적용(연산)을 위해 사용 (벡터 or 행렬로 리턴)

 - 내장 함수가 벡터 연산이 가능하더라도, 데이터 프레임과 같은 2차원 구조에 적용할 수 없는 사용자 함수의 경우 반드시 필요

 - 주 사용 목적은 2차원 구조(data frame)에 원소별 벡터 연산을 적용하기 위함


> sapply(v1, f1)

    a/b   aa/bb aaa/bbb 

    "a"    "aa"   "aaa"



4. tapply(vector, index, function) : '그룹별' 분할 함수 적용을 위해 사용(벡터로 리턴) => 그룹함수 연산

 - 분할 -> 적용 -> 결합, 순서로 연산 

 - aggregate, ddply를 통해서도 그룹 연산 가능(출력 결과 데이터 프레임)


> tapply(emp$SAL, emp$DEPTNO, mean, na.rm = T)    # 같은 부서(10,20,30) 내의 급여 평균

      10       20       30 

2916.667 2175.000 1566.667 



5. mapply(function, data...) : 함수에 다수의 인자를 적용하기 위해 사용(리스트로 리턴)

 - mapply의 인자가 스칼라일 경우, 각 함수에 동일 값이 적용


> mapply(substr, c('abc','bcde'), 1, 2)    # 적용 대상 ('abc','bcde')에 모두 1과 2라는 인자 적용 

 abc bcde 

"ab" "bc" 

> mapply(substr, c('abc','bcde'), c(1,2), c(2,3))  서로 다른 인자 전달 가능

 abc bcde 

"ab" "cd" 




2. group by 연산(ddply, aggregate, tapply)


1. plyr::ddply 분할, 적용, 조합을 수행하여 그룹별 연산을 위해 사용

   ddply(data,                # 전체 데이터 셋

            .(),                   # group by 컬럼

            ddply-func,       # ddply 내부 함수 (transform, mutate, summarise, subset)

            fun)                 # 그룹함수(컬럼이름과 함께 전달)


@ transform() : 원본 데이터 + ddply의 연산 결과를 컬럼 이름 지정과 함께 출력 

> ddply(Fruits, .(Year), transform, average = mean(Sales))   # 년도별 Sales 평균

    Fruit Year Location Sales Expenses Profit       Date  average

1  Apples 2008     West    98       78     20 2008-12-31 93.00000

2 Oranges 2008     East    96       81     15 2008-12-31 93.00000 ...


@ mutate() : transform과 유사하지만 순차적 연산처리를 할 경우 사용

> ddply(Fruits, .(Year), mutate, average = mean(Sales), avg_per = average/100)   # 인자의 결과를 다음 인자에 순차적으로 사용

    Fruit Year Location Sales Expenses Profit       Date  average   avg_per

1  Apples 2008     West    98       78     20 2008-12-31 93.00000 0.9300000

2 Oranges 2008     East    96       81     15 2008-12-31 93.00000 0.9300000 ...


@ summarise() : 그룹 연산 결과를 그룹 수에 맞게 요약 정보 제공                                              

> ddply(std, .(GRADE), summarise, avg_height = mean(HEIGHT), avg_weight = mean(WEIGHT))  # 그룹별 연산 

  GRADE avg_height avg_weight    

1     1      170.4       62.4

2     2      175.6       67.4

3     3      166.6       51.4

4     4      175.8       68.2


@ subset() : 그룹별 연산 결과를 사용하여 특정 조건을 만족하는 데이터만 출력 

> ddply(std, .(GRADE), subset, HEIGHT == max(HEIGHT),)[,c("NAME","GRADE","HEIGHT")]

    NAME GRADE HEIGHT

1 김주현     1    179

2 노정호     2    184

3 오나라     3    177

4 박동호     4    182



2. aggregate tapply() 함수와 유사한 그룹 연산 함수

   aggregate(x,        # 연산 대상, date frame 가능

                  by,       # group by 컬럼, list로 전달, 여러 컬럼 전달 가능 

                  FUN)    # 함수


> aggregate(std[,c('HEIGHT','WEIGHT')], by = list(std$GRADE), mean)

  Group.1 HEIGHT WEIGHT

1       1  170.4   62.4

2       2  175.6   67.4

3       3  166.6   51.4

4       4  175.8   68.2

> aggregate(std[,c('HEIGHT','WEIGHT')],               # student data에서 학년별, 학과별 키와 몸무게의 평균 

              by = list(std$GRADE, std$DEPTNO1), 

              mean)

   Group.1 Group.2 HEIGHT WEIGHT

1        1     101  162.0   48.0

2        2     101  182.0   72.0

3        3     101  164.0   48.0  ...


   aggregate(formula,   # 연산 대상 ~ group by 컬럼

                  data,       # 위를 포함한 전체 데이터 셋

                  FUN)   


> aggregate(HEIGHT ~ GRADE, std, mean)

  GRADE HEIGHT

1     1  170.4

2     2  175.6

3     3  166.6

4     4  175.8

> aggregate(cbind(HEIGHT, WEIGHT) ~ GRADE + DEPTNO1,     

                 std,                     # student data에서 '학년별, 학과별' '키와 몸무게'의 평균 

                 mean)                # 연산 대상의 컬럼 확장은 cbind() 사용, group by 는 '+'로 확장 가능     


   GRADE DEPTNO1 HEIGHT WEIGHT

1      1     101  162.0   48.0

2      2     101  182.0   72.0

3      3     101  164.0   48.0  ...



3. tapply(vector, index, function) : '그룹별' 분할 함수 적용을 위해 사용(벡터로 리턴) => 그룹함수 연산

 - 분할 -> 적용 -> 결합, 순서로 연산 

 - aggregate, ddply를 통해서도 그룹 연산 가능(출력 결과 데이터 프레임)


> tapply(emp$SAL, emp$DEPTNO, mean, na.rm = T)    # 같은 부서(10,20,30) 내의 급여 평균

      10       20       30 

2916.667 2175.000 1566.667 

> ddply(std, .(GRADE), summarise, avg_height = mean(HEIGHT))

  GRADE avg_height

1     1      170.4

2     2      175.6

3     3      166.6

4     4      175.8

> aggregate(std[,'HEIGHT'], by=list(std$GRADE), mean)

  Group.1     x

1       1 170.4

2       2 175.6

3       3 166.6

4       4 175.8

> aggregate(HEIGHT ~ GRADE, std, mean)

  GRADE HEIGHT

1     1  170.4

2     2  175.6

3     3  166.6

4     4  175.8

> tapply(std$HEIGHT, std$GRADE, mean)

    1     2     3     4 

170.4 175.6 166.6 175.8




3. dcast, melt <-> stack, unstack

  

1. reshape2::meltstack()함수처럼 동일 관측치의 값이 각 컬럼으로 분리되어 있는 경우 차곡차곡 쌓기 위해 사용

                        : stack()함수와 달리 일부 컬럼 고정(제외) 나머지 컬럼을 stack 처리

   melt(data,             # 원본 데이터

          id,                 # 고정 컬럼

          measure.var)   # stack처리 할 컬럼(생략 시 id컬럼 제외 모든 컬럼)


> melt(m1, id=c('year','mon'), measure.vars = 'latte')   # latte 데이터만 stack 처리

   year mon variable value

1  2000   1    latte   400

2  2000   2    latte   401  ...



2. reshape2::dcast unstack 함수처럼 이미 쌓여진(stacked) 컬럼을 각 항목별로 분리하기 위해 사용 -> 교차테이블 작성 

                         : 각 row와 column을 지정 가능하고, 품목별 가격, 품목별 수량 과 같이 표현

   dcast(data,                              # 원본 데이터 

           formula,                         # 행 고정 ~ unstack 처리 컬럼

           fun.aggregate = NULL,      # 데이터 축약 시 사용 (그룹, 결합)함수(default:length)  

           margins = NULL,              # 부분합 출력 시 TRUE

           value.var = guess_value(data))   # value 컬럼 지정(분리 할 컬럼), 생략 가능, 생략 시 마지막 컬럼 지정


> dcast(sales, 날짜 ~ 품목, fun.aggregate = sum)        # 날짜별, 품목 판매량 교차 테이블

        날짜   TV 냉장고 세탁기 에어컨

1 2018-01-01 2236   2588   1189   2114

2 2018-01-02 1144   1642   1733   1556

3 2018-01-03 1554   1536   1142   1362

> dcast(d2, year ~ name, margins = TRUE, fun.aggregate = sum)   # fun 생략 시 데이터 축약 -> 데이터 수 출력 

   year americano latte mocha (all)

1  2000      1000  1200  2200  4400

2  2001      1100  1250  2300  4650

3   (all)      2100  2450  4500  9050

> dcast(d2, year ~ name, value.var = 'qty')        # value.var 생략 시 자동으로 마지막 컬럼 선택

year americano latte mocha

1 2000       200   100    80

2 2001       210   120    70



3. stack(data) : 데이터를 그룹별로 쌓기


> stack(df)   

  values ind       # 퍼져있는 데이터들을 동일할 컬럼으로 쌓음. 값들은 values 대로, 키 값은 ind 대로 구분

1     90   m

2     89   m

3     84   m

4     94   f

5     87   f

6     87   f



4. unstack(data, formula) : 쌓여져 있는 컬럼을 서로 다른 컬럼으로 분리 (중복된 값(ex.연, 월, 일)이 있을 때 사용하면 유용)


> unstack(df_melt, latte ~ mon)     # latte의 월 별 판매 수량 

   X1  X2  X3  X4  X5  X6  X7  X8  X9 X10 X11 X12

1 400 401 402 403 404 405 406 407 408 409 410 411

2 412 413 414 415 416 417 418 419 420 421 422 423




4. sort, order, na 치환, ...


1. order(vector, na.last, decreasing) : 정렬된 쉘의 위치 값 리턴, 색인으로 데이터 정렬 (data frame 정렬 가능)


v1[order(v1)] 


2. sort(vectorna.last, decreasing) : 정렬된 데이터 바로 리턴 (data frame  정렬 불가능)


sort(v1) 


3. orderBy(formula = 나열컬럼 ~ 정렬컬럼, data = 원본) : 정렬된 데이터 바로 리턴, 내림차순 불가  (dataframe 정렬 가능)


orderBy( ~ DEPTNO + SAL, emp)


4. zoo::na.locf : NA를 이전 행 값으로 치환 

   na.locf(object, 

             fromLast)     # fromLast = TRUE : NA를 다음 행 값으로 치환


na.locf(subway)


5. na.omit(data) : NA 값을 포함하는 행 삭제 (dataframe  적용 가능)

   = tidyr::drop_na(data)




5. merge 

 

1. merge() : 데이터 병합(JOIN)

   merge(x, y,             # 조인할 두 데이터 프레임

            by = ,           # 조인 컬럼(양쪽 컬럼 이름이 같을 경우) 

            by.x = by,     # (첫 번째 데이터 조인 컬럼, 조인 컬럼이 다수이면 벡터로 전달)

            by.y = by,     # (두 번째 데이터 조인 컬럼, 조인 컬럼이 다수이면 벡터로 전달)   

            all = FALSE,   # Full(x,y) Outer Join

            all.x = all,     # Left(x) Outer Join

            all.y = all)     # Right(y) Outer Join


emp와 dept의 join  (조인 컬럼 이름이 다를 경우)

> merge(emp, dept, by.x = 'DEPTNO1', by.y = 'DEPTNO2')[ , c("ENAME","DEPTNO","DNAME")]  

# 첫 번째 데이터 기준 Outer Join

> merge(std, professor, by.x = 'PROFNO', by.y = 'PROFNO',

         all.x = TRUE)[,c('NAME.x','NAME.y')]           

# Self Join

> merge(emp, emp, by.x='MGR', by.y='EMPNO',all.x=TRUE)[,c('ENAME.x','SAL.x','ENAME.y','SAL.y')]  




반응형

'R' 카테고리의 다른 글

[R 정리] 시각화  (0) 2019.01.29
[R 정리] 데이터 가공을 위한 주요 함수 정리  (6) 2019.01.13
댓글
최근에 올라온 글
최근에 달린 댓글
링크
Total
Today
Yesterday