티스토리 뷰
데이터 그룹 연산을 위한 주요 함수 정리
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::melt : stack()함수처럼 동일 관측치의 값이 각 컬럼으로 분리되어 있는 경우 차곡차곡 쌓기 위해 사용
: 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(vector, na.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 |