SQL의 window Function : 행과 행 간의 관계 정의. 순서, 집계, 순서, 비율
SHIFT
시계열 데이터의 인덱스를 기준으로 데이터/값을 원하는 방향으로 이동시키는(shift) 메서드
DataFrame.shift(periods=기간, freq=, axis=0, fill_value='비었음')
- 주요 파라미터
- periods: 이동할 기간(칸). 음수 또는 양수로 입력.
+1 미래로, n만큼 이전 행을 뒤로 미는것 df.shift(1)
-1 과거로, 미래 행을 앞으로 땡겨오는 것 df.shift(-1) - freq: 선택 매개변수.날짜 단위로 이동
Y년, M월, D일, H시, T분, S초, Timestamp, 'Infer'자동으로 적당하게 분석 등이 위치 - fill_value: shift로 인해 생긴 결측치의 대체값 지정
- axis: 연산할 축방향 설정. 0(행) / 1(열)
- periods: 이동할 기간(칸). 음수 또는 양수로 입력.
- df.shift(1).head() #뒤의 날짜의 데이터를 미래로 이동 (이전 값을 뒤로 한칸 밀기)
- df.shift(-1).head() # 앞의 날짜의 데이터를 과거로 이동(이후 값들을 앞으로 한칸 땡기기)
- df.shift(periods=3,freq='D') # 3일 이동
- df.shift(periods=3,freq='infer') # df의 날짜간격을 분석해서 적당한 주기를 이동
Rolling - 시계열 데이터, 이동평균
여러개의 데이터가 시간순으로 있을 때, 특정기간(window, 범위)안의 값으로 추가 연산하여 계산하는 메서드
이동평균, 이동합 등 구할때 사용
-> 시간에 따른 데이터의 "추이"를 계속 이동하면서 확인할 수 있음(트렌드 파악)
: 주가데이터, 날씨 데이터, 판매량 데이터 etc
DataFrame.rolling(window, min_periods=None, center=False, win_type=None, on=None, axis=0, closed=None, method='single').추가메서드()
- 나(인덱스)를 포함(1) + 앞의 컬럼 (window size-1)개를 가져와서 계산 : closed=right(기본값)
- 주요 파라미터
- window: 계산할 창(window)/기간/구간의 크기. 열 기준으로 계산할 경우 행의 수 / 날짜 데이터의 경우 '일'
- min_periods: 계산할 최소 크기(기간) . 기본적으로 window 크기와 동일.
- center: 계산을 중간 행에서 할 지 결정하는 파라미터. 기본값 False(창의 마지막 값을 기준으로 계산)
True 로 할 경우 창의 중앙값을 기준으로 계산(더 균형잡힌 방식으로 배치 가능) - win_type: triang / gaussian 등 가중치를 넣어 계산할 경우 계산 방식.
- on: 시계열 인덱스나, 시계열과 유사한 열이 있을 경우 이 열을 기준으로 rolling을 수행할지 설정
- axis : 계산할 방향 0(행) / 1(열)
- closed: 연산이 닫히는 방향을 설정(경계값 포함여부) left / right / both / neither
- right: 오른쪽 값을 포함하여 계산 = 현재를 포함한 window size 개의 계산
- left: 왼쪽 값을 포함하여 계산 = 현재을 제외하고 앞 window size 개의 계산
- both: 양쪽을 포함하여 계산= window size만큼 현재 행 + 양쪽(앞뒤/왼오른쪽) 모두 포함하여 계산
- neither: 양쪽을 포함하지 않고 계산 = 현재 행 + 양쪽값(앞뒤) 모두 제외 -> 그냥 다 NaN
- method:{'single' / 'table'} numba를 이용하여 테이블 계산을 진행하여 속도를 높힐지 여부. 현재 'single'만 사용가능.
📌 핵심 원리
1. **window 크기(기간)**를 설정한다.
2. 데이터의 앞에서부터 순차적으로 window 크기만큼의 값들을 가져와 평균을 계산한다.
3. 결과를 새로운 컬럼에 저장한다.
df['이동평균'] = df['컬럼명'].rolling(window=창크기).mean()
- 예시
- df.rolling(window=3).mean() # 3일 이동평균 구하기
기본 rolling은 창의 마지막 값을 기준으로 (앞의 n-1개의 행과 합쳐서) 이동평균을 계산.
-> 그래서 맨 앞의 행에 NaN이 뜸 (맨앞에 행에는 더 앞의 값이 없으니까) - df.rolling(window=3, center=True).mean() #3일 이동평균을 중간행을 기준으로 계산
3일의 이동평균이 해당 중간행을 기준으로 (양옆 행을 가져와) 계산 - df.rolling(window=3).sum() # 3일 누적합 구하기
- df.rolling(window=3, center=Ture, closed='left').mean() # 3일 이동평균을 중간 행을 기준으로 계산하고, 왼쪽 값을 포함하여 계산
- df.rolling(window=3).mean() # 3일 이동평균 구하기
Expanding - 누적합, 누적평균
행이나 열의 값에 대해 누적으로 연산을 수행하는 메서드
처음부터 해당 행(열)까지 모든 값을 포함하여 계산, 점점 커짐
df.expanding(min_periods=1, axis=0, method='single').추가메서드()
- 주요 파라미터
- min_periods: 연산을 수행할 요소의 최소 갯수. 이보다 작으면 NaN을 출력
- axis : 연산할 축방향 설정. 0(행) / 1(열)
- method: 연산방식. single(연산을 한 줄씩 수행) table(전체 테이블에 대해서 롤링수행).
기본값 single , 롤링 연산할 경우 numba 라이브러리 추가로 import 필요.
- 예시
- df.expanding(axis=1).sum() #열 기준으로 누적합 계산
- df.expanding().mean() #첫 행부터 현재 행까지의 평균을 계산
데이터타입별 상관관계
상관관계 : 두 변수간의 직선관계
상관계수 : -1 ~ 1 사이의 값
+1에 가까울수록 양의 상관관계(비례)
0 에 가까울수록 선형적인 관계가 아님
- 1에 가까울 수록 음의 상관관계(반비례)
****상관관계는 인과관계(원인과 결과)와 다름!!!!! ****

상관계수 r : 변수간의 관계(선형 상관관계)의 강도를 나타내는 값
p-value : 해당 상관관계가 우연히 발생했을 확률(유의확률)
p-value<0.05 이면 "진짜 관계가 있다!" 라고 확신 가능 = 유의미한 관계라고 판단 가능
=> 상관계수만 보면 "강한 관계"로 보이지만, 실제로는 우연일 수 있음
p-value가 작아야 "진짜 관계"라고 확신 가능
=> 상관계수 r + p-value를 함께 봐야 신뢰할 수 있는 분석이 가능 !!!!!!!
연속형 - 연속형 : 피어슨 상관계수
결과값 : -1 ~ +1 사이
| 상관계수(절대값) r | 해석 |
| 0.9 ~ 1.0 | 매우 높은 음/양의 상관관계 |
| 0.7 ~ 0.9 | 높은 음/양의 상관관계 |
| 0.5 ~ 0.7 | 약한 음/양의 상관관계 |
| 0.0 ~ 0.5 | 거의 상관관계가 없음 |
#### 파이썬 코드 #####
#피어슨 상관계수 계산
correlatioin = df.corr(method='pearson')
print(correlation)

상관계수 1.0 = 강한 상관계수 = customer_zip_code_prefix 과 customer_zip_code_prefix 은 같음
연속형 - 범주형(이분형) : Point-Biserial Correlation - 0/1 변환 + 피어슨 상관계수
이분형 변수를 0/1로 코딩한 뒤-> 피어슨 상관계수로 계산 = Point-Biserial Correlation
##### 파이썬코드 ####
python scipy 라이브러리의 pointbiserialr 함수를 이용
r, p_value = stat.pointbiserialr(변수1,변수2)
주의점: 연속형 변수와 범주형 변수에 대한 상관관계를 해석할 때에는,
단순 통계량(r)만 확인하는 것이 아닌, p-value(통계적으로 설명 가능한지) 를 함께 살펴봐야함.

연속형 - 범주형(3개 이상) : ANOVA 검정
범주형 변수가 명목형(순서x 범주형 변수)일 때, 범주형 변수에 따라 연속형 변수의 평균에 얼마나 차이가 있는지 검정
c.f 연속형-범주형 변수일때(2개), 두 그룹의 평균에 얼마나 차이가 있는지 비교 = t-검정
t-test(t-검정) 결과값 #p-value 로 평가 가능
결과값 -1 ~ +1
| 상관계수(절대값) | 해석 |
| 0.9 ~ 1.0 | 매우 높은 음/양의 상관관계 |
| 0.7 ~ 0.9 | 높은 음/양의 상관관계 |
| 0.5 ~ 0.7 | 약한 음/양의 상관관계 |
| 0.0 ~ 0.5 | 거의 상관관계가 없음 |
ANOVA 검정 = 범주형 변수에 따라 연속형 변수의 평균 차이를 검정하는 방법
= 1. 범주형 변수를 기준으로 데이터를 나누고,
2. 그에 따른 연속형 변수의 평균 차이를 비교해야함
##### 파이썬코드 ####
1. 범주형 변수를 기준으로 연속형 변수를 나누고,
groups = [df['price'][df['club_member_status'] == category] for category in df['club_member_status'].unique()]
3. 필요한 값(연속형변수) 2.카테고리와 같은 행만 필터링 4.반복문for 1.범주형 변수에 존재하는 고유값(카테고리)
: 카테고리를 status(범주형변수)의 unique 값들로 지정하고, 이를 모든 행에 적용(for문), 결과적으로 필터링 된 데이터셋 중에서 price 컬럼만 가져오는 코드
2. 그에 따른 연속형 변수의 평균 차이를 비교해야함
python scipy 라이브러리의 f_oneway 함수
f_stat, p_value = stats.f_oneway(변수1,변수2,변수3)
-> ANOVA 검정을 통해, ## F-Statistic, p-value 도출
| 검정통계량(F) | 해석 |
| F <1 | 무의미 |
| 1 <= F < 3 | 거의 무의미 |
| 3 <= F <10 | 경우에 따라 유의미 |
| 10 <= F < 50 | 유의미(강한차이) |
| F > 50 | 거의 확실한 유의미(아주 강한차이) |
| F >= 100 | 확실한 유의미(매우 강한차이) |
주의점: 연속형 변수와 범주형 변수에 대한 상관관계를 해석할 때에는,
단순 통계량(r)만 확인하는 것이 아닌, p-value(유의확률, 통계적으로 설명 가능한지) 를 함께 살펴보아야 합니다.
# F= 150 -> 확실한 유의미
-> 클럽멤버상태(범주형변수)에 따라서 나눠진 그룹 price의 평균의 차이가 크다. = 통계적으로 설명 가능하다

범주형 - 범주형 : 파이 상관계수( Cramer's V )
범주형 변수(명목형)끼리 상관관계 확인하기
방법 : 두 범주형 변수를 0과 1로 코딩(숫자로 변환) → Pearson 상관계수를 구하기
각 범주형 변수는 2가지 값을 가지는 경우(이분형 변수) + 명목형(순서가 없는 범주) 여야 함.
- Cramer's V 계수 : 두 범주형 변수 중 하나의 변수가 3개 이상의 범위를 가지는 경우 사용
- step1. 범주형 변수의 값들을 LabelEncoding = 범주형 변수들이 연속형 변수(숫자형태)로 바꼈음
- Encoding : 범주형 변수-> 수치형변수로 바꿔주기
- LabelEncoding : 문자열의 unique값 -> 숫자로 바꿔줌 (하나씩) (mapping 개념)
- one hot encoding : 목록화 한 후 목록값(속성)에 이진값(0/1) 할당
- 다중 공선성 문제로 머신러닝시 조심해야함
- step2. define a function
- step3. 혼동행렬 생성
- step1. 범주형 변수의 값들을 LabelEncoding = 범주형 변수들이 연속형 변수(숫자형태)로 바꼈음
def cramers_V(var1,var2) :
crosstab =np.array(pd.crosstab(var1,var2, rownames=None, colnames=None)) # Cross table building
stat = chi2_contingency(crosstab)[0] # Keeping of the test statistic of the Chi2 test #빈도표
obs = np.sum(crosstab) # Number of observations
phi2 = stat / obs
r, k = crosstab.shape
phi2corr = max(0, phi2 - (((k-1)*(r-1))/(obs - 1)))
rcorr = r - ((r-1)**2)/(obs-1)
kcorr = k - ((k-1)**2)/(obs-1)
return np.sqrt(phi2corr / min((kcorr-1), (rcorr-1)))
rows= []
for var1 in data_encoded:
col = []
for var2 in data_encoded :
cramers =cramers_V(data_encoded[var1], data_encoded[var2]) # Cramer's V test
col.append(round(cramers,2)) # Keeping of the rounded value of the Cramer's V
rows.append(col)
cramers_results = np.array(rows)
data_encoded_df = pd.DataFrame(cramers_results, columns = data_encoded.columns, index =data_encoded.columns)
data_encoded_df
- Cramer's V 계수는 0과 1 사이의 값으로 나타남.
| Cramer's V 계수(0~1) | 계수 해석 |
| 0 - 0.1 | 무시해도 되는 관계 |
| 0.1 - 0.2 | 약한 상관관계 |
| 0.2 - 0.4 | 보통의 상관관계 |
| 0.4 - 0.6 | 약한 상관관계 |
| 0.6 - 0.8 | 강한 상관관계 |
| 0.8 - 1.0 | 매우 강한 상관관계 |
Cramer's V 계수는 python scipy 라이브러리와 sklearn 라이브러리로 구현
# 히트맵 그래프

'데이터 분석 > Python' 카테고리의 다른 글
| python 패턴북 (0) | 2025.04.08 |
|---|---|
| 데이터 전처리(Scaling) : 데이터 표준화/정규화, 로그, KNN (0) | 2025.04.08 |
| df 형태 변환 5가지 : Transpose, pivot_table, melt, stack, unstack (0) | 2025.04.03 |
| Pandas 메소드와 함수 (0) | 2025.03.19 |
| 결측치, 이상치(Z-SCORE, IQR) (0) | 2025.03.18 |
