연관분석(Association Analysis)
- 사건의 연관규칙을 찾는 방법
- A후에 B를 시행할 확률을 구하는데 사용
- 소비자의 구매 패턴 분석에 주로 사용됨
- 장바구니분석이라고도 불림
- 유투브, 넷플릭스 등과 같은 플랫폼도 이러한 알고리즘을 기반으로 콘텐츠를 추천
- 연관규칙을 찾기 전 연관성이 있는지를 파악한다.(Run-test)
- 이후 연관규칙분석을 실시한다(Aporiori)
- 연관분석에 사용되는 척도
척도명 | 내용 |
지지도 | - 전체 거래중 A와 B가 함께 거래된 비율 - A와 B를 모두 포함하는 거래 수 / 전체거래수 |
신뢰도 | - A를 구매한 거래중 A와 B가 함께 거래된 비율 - 연관성의 정도를 파악 가능 - 지지도 / A구매비율 |
향상도 | - A가 구매되지 않았을때 B의 구매 확률보다 A가 구매되었을때 B가 구매될 확률 증가비 - 향상도=1 일경우 두 품목은 관련이 없음 - 지지도 / (A구매비율 * B구매비율) |
1. Run-test
- 연관규칙을 찾기 전 연속적인 binary값들이 임의적으로 나타난 값인지 아닌지를 검정하는 기법
가설 | 내용 |
H0 | 연속된 값이 임의적이다(연관성이 없다) |
H1 | 연속된 값이 임의적이 아니다(연관성이 있다) |
- statsmodels.sandbox.stats.runstest_1samp(parameters)
statsmodels.sandbox.stats.runs.runstest_1samp - statsmodels 0.14.1
statsmodels.sandbox.stats.runs.runstest_1samp statsmodels.sandbox.stats.runs.runstest_1samp(x, cutoff='mean', correction=True)[source] use runs test on binary discretized data above/below cutoff Parameters: xarray_likedata, numeric cutoff{‘mean’, ‘me
www.statsmodels.org
예시) 임의 데이터를 활용한 연관규칙검정(Run-test)
- 데이터정의
- 임의 데이터를 만듬
- Run-test의 경우 binary데이터(이진데이터)만 가능
#데이터 정의
data = ["a", "a", "b", "b", "a", "a", "a", "a", "b", "b", "b", "b", "b", "a", "a", "b", "b", "a", "b", "b"]
df = pd.DataFrame(data, columns=["product"])
df.head()
- 변환 및 검정
- binary데이터로 바꿔주는 작업을 실시한다
- run-test실행 결과 p-value > .05 이므로 귀무가설을 채택한다.
- 따라서 a, b는 임의적이다 = 연관성이 없다.
#데이터 변환
df.loc[df.loc[:, "product"] == "a", "product"] = 1 #a=1
df.loc[df.loc[:, "product"] == "b", "product"] = 0 #b=0
#runstest_1samp
from statsmodels.sandbox.stats.runs import runstest_1samp
z, p = runstest_1samp(df["product"], cutoff=0.5, correction=True)
print(f"z-stat: {z}\np-value: {p}")
'''
z-stat: -1.1144881152070183
p-value: 0.26506984027306035
'''
2. Aporiori
- 가능한 모든 경우의 수를 탐색하여 지지도, 신뢰도, 향상도가 높은 규칙들을 찾아내는 방식이 가장 이상적
- 하지만 아이템 수가 증가할 수록 계산에 소요되는 시간이 기하급수적으로 늘어남
- 아이템이 n개일때 탐색할 모든 경우의 수 = n*(n-1)
- 따라서 최소지지도 이상의 빈발항목집합을 찾은 후 그것들에 대해서만 연관규칙 계산
- 빈발항목집합: 최소지지도보다 큰 지지도 값을 갖는 품목의 집합
- from mlxtend.preprocessing import TransactionEncoder: 데이터세트를 트랜잭션 데이터로 변경
- from mlxtend.frequent_patterns import apriori: 빈번항목집합을 출력
- from mlxtend.frequent_patterns import association_rules: score(점수), confidence(신뢰도), Lift(향상도)를 DataFrame으로 생성
Apriori - mlxtend
From here you can search these documents. Enter your search terms below.
rasbt.github.io
예시) groceries데이터로 연관규칙분석 실행
- 데이터정의 및 전처리
- 데이터는 csv형태로 되어 있었음
- value가 str형태로 들어가 있었음 > ','단위로 split하여 2차원 데이터 형태로 변경
#데이터 컬럼명 변경
df.columns = ["product"]
df.columns
#데이터 전처리: str으로 되어있던 value값을 리스트로 변경
product_series = df.iloc[:,0].str.split(",")
#내역의 unique값 확인: null없음
unique_products = [p for product in product_series for p in product]
unique_products = np.unique(unique_products)
#트랜잭션데이터로 만들기 위해 2차원 데이터로 변환
groceries = [pl for pl in product_series]
groceries[:5]
- 트랜잭션데이터 변경
#트랜잭션 데이터로 변경
from mlxtend.preprocessing import TransactionEncoder
te = TransactionEncoder()
encoded_groceries = te.fit_transform(groceries)
encoded_groceries
#DataFrame형식으로 변환
encoded_groceries_df = pd.DataFrame(encoded_groceries, columns=te.columns_) #te.columns_를 하면 groceries의 unique한 값들이 나옴
encoded_groceries_df.head()
- 빈번항목집합(최소지지도 이상의 지지도를 갖는 품목들) 탐색
- 조건에 부합하는 품목들중 412번을 해석하면 다음과 같다. (butter, other vegetables)를 구매하면 whole milk를 구매할 확률이 57%로 나타난다. 그리고 (butter, other vegetables)를 구매하지 않고 whole milk를 구매할 확률보다 (butter, other vegetables)를 구매하고 whole milk를 구매할 확률이 2.45배 높다.
#---------- 빈번항목집합 탐색
from mlxtend.frequent_patterns import apriori
#지지도가 1%이상인 빈번항목집단 추출
ap = apriori(encoded_groceries_df, min_support=0.01, use_colnames=True)
#---------- 연관규칙분석 수행
from mlxtend.frequent_patterns import association_rules
# 빈번항목집단에서 향상도가 1이상인 연관규칙
rules = association_rules(ap, metric="lift", min_threshold=1)
rules.head()
# 2개이상 구매했을때 추가로 구매하는 물품 확인
# 조건1: 먼저 구매한 물품이 2개 이상 / 신뢰도: 0.4이상 / 향상도: 2이상
#규칙 길이 정하기
rules["antecedents_len"] = rules["antecedents"].apply(lambda x: len(x))
rules.head()
#조건 만족하는것들 추출
rules[
(rules["antecedents_len"] >= 2) &
(rules["confidence"] >= 0.4) &
(rules["lift"] >= 2)
]
'Data Analysis > Statistics' 카테고리의 다른 글
Python_Statistics_TimeSeries (0) | 2024.03.14 |
---|---|
Python_Statistics_Cluster (0) | 2024.03.07 |
Python_Statistics_Regression (0) | 2024.03.01 |
Python_Statistics_Chi-square (0) | 2023.12.15 |
Python_Statistics_Anova(분산분석) (0) | 2023.12.11 |