핵심 요약
데이터 마트의 목적, 요약·파생변수와 RFM, 집계·결합·long/wide 변환의 기본을 정리한다.
본문
데이터 마트 목적·그레인·차원·측정값
데이터 마트는 특정 업무나 분석 주제에 필요한 데이터를 일관된 기준으로 모은 분석용 집합이다. 가장 먼저 정할 것은 한 행이 무엇을 뜻하는지, 즉 그레인(grain)이다.
예를 들어 한 행이 주문 1건인지 고객-월 1행인지에 따라 가능한 집계와 결합이 달라진다.
- 차원: 지역, 상품, 고객군, 날짜처럼 분석 기준이 되는 속성
- 측정값: 매출, 수량, 비용처럼 집계할 값
그레인이 섞이면 같은 금액이 중복 집계되거나 지표의 분모가 잘못될 수 있다.
합계·비율·고유 개체 수와 거래·스냅샷 집계
매출처럼 단순 합계가 가능한 값과 전환율·평균처럼 분자·분모에서 다시 계산해야 하는 지표를 구분한다. 일별 전환율을 단순히 더하거나 평균내면 일별 방문자 수 차이를 무시할 수 있다.
고유 고객 수도 주의한다. A상품 고객 100명과 B상품 고객 80명을 더해 전체 고객이 180명이라고 할 수 없는 이유는 두 집단에 같은 고객이 있을 수 있기 때문이다.
스냅샷 데이터는 특정 시점의 상태를 기록한다. 월말 재고 스냅샷을 날짜별로 단순 합계하면 같은 재고가 여러 번 더해질 수 있으므로 의미에 맞는 시점 집계가 필요하다.
base R 집계에는 aggregate()와 tapply() 등을 사용할 수 있다. 예시는 다음과 같다.
d <- data.frame(
region = c("A", "A", "B"),
sales = c(10, 20, 15)
)
aggregate(sales ~ region, d, sum)
# region sales
# 1 A 30
# 2 B 15
tapply()는 벡터를 그룹별로 나누어 함수를 적용하고, xtabs()는 수식에 따라 범주 조합별 값을 교차집계할 수 있다.
sales <- c(40, 60, 30, 90)
region <- c("E", "E", "W", "W")
tapply(sales, region, mean)
# E W
# 50 60
d2 <- data.frame(
region = c("E", "E", "W", "W"),
channel = c("web", "store", "web", "web"),
amount = c(10, 20, 30, 40)
)
xtabs(amount ~ region + channel, data = d2)["W", "web"]
# [1] 70
과거 원천 이력이 불변이고 신규 구간만 추가된다는 전제라면 신규 기간만 같은 규칙으로 계산하는 증분 집계를 사용할 수 있다. 다만 과거 수정이나 지연 도착 데이터가 있을 수 있는 시스템이라면 해당 기간의 재처리·정정 규칙을 별도로 둔다.
결합 키·카디널리티와 inner/left join
데이터 결합은 열을 붙이기 전에 키가 무엇을 식별하는지와 양쪽 카디널리티가 어떤지 확인해야 한다.
- 1:1: 양쪽에서 키가 유일
- 1:N: 한쪽 키 하나가 다른 쪽 여러 행과 연결
- N:M: 양쪽 모두 중복되어 행 수가 예상보다 크게 늘 수 있음
inner join은 양쪽에 모두 존재하는 키만 남기고, left join은 왼쪽 행을 유지하면서 오른쪽 정보를 붙인다.
left <- data.frame(id = c(1,2,3), x = c("a","b","c"))
right <- data.frame(id = c(2,3), y = c(20,30))
merge(left, right, by = "id", all.x = TRUE)
# id x y
# 1 1 a NA
# 2 2 b 20
# 3 3 c 30
결합 전후 행 수와 키 중복 수를 확인하면 다대다 결합 오류를 찾는 데 도움이 된다.
base R의 merge(x, y)에서 by를 생략하면 양쪽 데이터프레임에 공통으로 존재하는 열 이름들의 교집합이 기본 결합키가 된다. 의도한 키가 하나뿐이라면 by="customer_id"처럼 명시하는 편이 안전하다.
x <- data.frame(
customer_id = c(1, 1),
date = c("D1", "D2"),
xval = c(10, 20)
)
y <- data.frame(
customer_id = 1,
date = "D2",
yval = 99
)
nrow(merge(x, y))
# [1] 1
nrow(merge(x, y, by = "customer_id"))
# [1] 2
첫 결합은 customer_id와 date를 모두 키로 사용하지만, 두 번째 결합은 고객 ID만 키로 사용한다.
long· wide 변환과 복합 키
long 형식은 한 관측의 여러 반복 측정이 행으로 길게 내려가고, wide 형식은 측정 시점·항목이 열로 펼쳐진 형태다. 분석·시각화·모델 입력 목적에 따라 변환한다.
고객ID + 날짜처럼 하나의 열로 유일하지 않으면 여러 열을 묶은 복합 키가 필요하다. 열 이름이 같아도 날짜 단위나 코드 기준이 다르면 같은 키라고 볼 수 없다.
파생변수·구간화·그룹 파생값과 재현 가능한 변환 규칙
파생변수는 원자료를 분석 목적에 맞게 다시 표현한 값이다. 예를 들어 주문금액과 수량으로 객단가를 만들거나 연령을 구간화할 수 있다.
cut(
c(5, 15, 25),
breaks = c(0, 10, 20, Inf),
labels = c("L", "M", "H"),
right = FALSE
)
# [1] L M H
# Levels: L M H
구간 경계, 결측 처리, 포함 방향(right)을 기록해야 다른 사람이 같은 값을 재현할 수 있다. transform()으로 계산 열을 추가하거나 ave()로 그룹별 평균·순위 같은 값을 원래 행에 붙일 수 있다. 어떤 함수를 쓰든 계산식, 그룹 기준, 예외 규칙을 문서화해야 다른 사람이 같은 값을 재현할 수 있다.
cut()은 경계 포함 방향을 명시해야 한다. 기본 right=TRUE에서는 구간이 (a,b]처럼 오른쪽이 닫히고, include.lowest=TRUE는 최저 경계도 첫 구간에 포함시킨다.
cut(
c(0, 10, 20),
breaks = c(0, 10, 20),
labels = c("low", "high"),
include.lowest = TRUE,
right = TRUE
)
# [1] low low high
# Levels: low high
따라서 동일한 경계값이라도 right와 include.lowest 설정이 달라지면 소속 구간이 바뀔 수 있다.
ADsP 시험 핵심 보충
- 데이터 마트는 특정 부서·주제의 분석을 위해 필요한 데이터를 구성한 부분 집합이다. 분석 목적과 분석 단위를 먼저 정한다.
- 요약변수는 여러 원천 값을 집계해 자주 사용하는 분석 정보를 만든 것이다. 파생변수는 분석 목적에 따라 계산식·조건·규칙으로 새 의미를 만든 것이다. 둘은 표현 목적에 따라 겹칠 수 있으므로 문항의 생성 규칙을 확인한다.
- RFM은 Recency(최근 구매), Frequency(정한 분석기간의 구매 빈도), Monetary(정한 분석기간의 총 구매금액)의 세 지표로 고객을 분석한다. 최근 구매일로부터 경과한 일수로 Recency를 측정하면 작을수록 더 최근 구매한 고객이다.
복습 문제
답을 생각한 뒤 정답과 근거를 펼쳐 보세요.
위 aggregate() 결과에서 A지역 매출 합계는?
정답과 근거
30이다. A지역의 10과 20을 합한 값이다.
left join 결과에서 id=1의 y가 NA인 이유는?
정답과 근거
오른쪽 테이블에 id=1이 없기 때문이다. left join은 왼쪽 행을 유지하고 대응값이 없으면 NA를 둔다.
고객ID가 양쪽 테이블에서 모두 중복되어 있으면 어떤 결합 문제가 생길 수 있는가?
정답과 근거
다대다(N:M) 결합으로 행이 곱처럼 증가해 측정값이 중복 집계될 수 있다. 결합 전 키 유일성과 카디널리티를 확인해야 한다.
예를 들어 한 행이 주문 1건인지 고객-월 1행인지에 따라 가능한 집계와 결합이 달라진다.
cut() 예제에서 15는 어느 구간에 속하는가?
정답과 근거
M이다. right=FALSE이므로 구간은 [10,20) 방식이며 15는 M에 속한다.