빅데이터(파이썬)/DA_Forecasts for Product Demand

Forecasts for Product Demand (2) 데이터 탐색 및 시각화

LearnerToRunner 2022. 12. 27. 23:14

Forecasts for Product Demand

데이터 탐색 및 시각화

AutoViz, SweetViz를 이용하는 방법도 있지만

간만에 복습할 겸 직접 시각화 해보았습니다

 


(참고) 데이터 셋 내 칼럼

'Product_Code', 'Warehouse', 'Product_Category', 'Date', 'Order_Demand'


 

제품 코드 관점 탐색

무슨 제품이 다수의 오더 디맨드를 차지하는가? 파레토의 원칙이 적용되는가?

파레토의 원칙
파레토 법칙은 ‘이탈리아 인구의 20%가 이탈리아 전체 부의 80%를 가지고 있다.’고 주장한 이탈리아의 경제학자 빌프레도 파레토의 이름에서 따왔다고 한다. 파레토 법칙은 ‘2080법칙’이라고도 하는데 ‘전체 결과의 80%가 전체 원인의 20%에서 일어나는 현상’을 의미한다.

출처


총 2160의 제품 중 Total demand의 80%를 차지하는 제품은 84종이다
(전체 종류의 3.8%)

파레토의 원칙은 적용되지 않지만
소수의 품종이 나머지 96.2%보다
규모상
더 큰 중요성을 갖는다

 

근거

# 제품별 전체수요
grp_byPC = df.groupby('Product_Code', as_index=False)['Order_Demand'].sum() #제품 수요 합계
grp_byPC = pd.DataFrame(grp_byPC).sort_values(by = 'Order_Demand', ascending=False, ignore_index=True) #데이터프레임 변화 후 Order_Demand에 따라 내림차순 정렬
grp_byPC['Demand_Proportion'] = (grp_byPC['Order_Demand']/grp_byPC['Order_Demand'].sum()) #전체 판매량의 기여도를 pct로 변환
grp_byPC['Demand_Accumulated'] = grp_byPC['Demand_Proportion'].cumsum() #기여도 누적합계
grp_byPC['Demand_80pct'] = 0
grp_byPC.loc[grp_byPC['Demand_Accumulated'] <= 0.8, 'Demand_80pct'] = 1 #Demand 기여도 80%에 든다면 1로 표기

print(grp_byPC)
print(grp_byPC[grp_byPC['Demand_80pct'] == 1]['Product_Code'].unique())
print(grp_byPC[grp_byPC['Demand_80pct'] == 1]['Product_Code'].nunique())
print(grp_byPC['Product_Code'].nunique())
print(grp_byPC[grp_byPC['Demand_80pct'] == 1]['Product_Code'].nunique() / grp_byPC['Product_Code'].nunique())

ls_pcin80 = grp_byPC[grp_byPC['Demand_80pct'] == 1]['Product_Code'].unique() # Demand 상위 80%내 제품의 제품코드

 

print(grp_byPC)
print(grp_byPC[grp_byPC['Demand_80pct'] == 1]['Product_Code'].unique())
나머지 프린트 결과


제품 카테고리 관점 분석

카테고리별로 Order Demand 구성 비율은?

제품카테고리 33개 중 상위 카테고리 5개(15%)가
전체 Demand의 97%를 차지한다
19(82.7%), 6(7.9%), 5(3.9%), 7(2.5%)

근거
# 카테고리
grp_byPCAT = df.groupby('Product_Category', as_index=False)['Order_Demand'].sum() #제품 수요 합계
grp_byPCAT = pd.DataFrame(grp_byPCAT).sort_values(by = 'Order_Demand', ascending=False, ignore_index=True) #데이터프레임 변화 후 Order_Demand에 따라 내림차순 정렬

print(grp_byPCAT['Product_Category'].nunique()) # 전체 제품 카테고리 수
plt.pie(grp_byPCAT['Order_Demand'], labels = grp_byPCAT['Product_Category'], autopct='%.1f')
plt.title('Proportion of Order Demand By Product_Category')
plt.legend(loc='best')
plt.show()

ls_pcat_top4 = [19, 6, 5, 7] #Demand 상위 97%의 제품 카테고리 번호

 

제품 카테고리 별 Order Demand 구성비율


웨어하우스 관점 분석

웨어하우스 별로 취급하는 제품 종류는 몇 개 인가?

웨어하우스 별로 취급하는 제품 카테고리는 몇 종류인가?

웨어하우스 별 발생하는 Order Demand의 기본 Stats은 어떤가?

 

웨어하우스 별로 취급하는 제품 종류는 몇 개 인가?
웨어하우스 J가 가장 많은 종류의 제품을 취급한다. (전체 제품종류의 75.2%)
이후 S > A > C 순
참고) 제품종류는 2,160개 이다

웨어하우스 별로 취급하는 제품 카테고리는 몇 종류인가?
웨어하우스 S가 가장 많은 제품 카테고리를 취급한다 (전체 카테고리의 84.8%)
이후 J/A > C 순 
참고) 제품카테고리 종류는 33개 이다

웨어하우스 별 발생하는 Order Demand의 기본 Stats은 어떤가?
아래 시각자료 참고

# Order Demand By Warehouse Boxplot
sns.boxplot(data = df, x='Warehouse', y='Order_Demand')
plt.title('ORDER DEMAND BOXPLOT BY WAREHOUSE')
plt.show()

 

웨어하우스의 min, max의 절대값이 같은 것을 고려했을 때 오더 취소일 가능성이 있다. 추후 음수로 된 데이터가 취소를 의미하는 것이 맞는지 확인해보기


아래 그래프 중 좌측은 
Order Demand를 웨어하우스별로 boxplot한 자료이며
우측 그래프는 박스플랏만을 확대한 그래프이다

이상치가 존재하며 음수의 Order demand 데이터도 다수 존재한다


 

Order Demand 관점 탐색

Order Demand 값은 어떻게 분포하는가?
-20,000 ~ 30,000에 대부분 분포한다

(좌) KDE PLOT, (우) 확대

Order Demand 음수값의 비율은 어느정도인가?
1%

아래는 그래프 두 개는
Order Demand를 웨어하우스별로 시각화 한 것
(좌) 웨어하우스별 Order demand
(우) Order Demand 음수, 양수 구분에 따른 분포


Order Demand 음수값은 오더의 의미를 취소하는가?
오더 수량 취소 또는 조정으로 볼 수 있다
조정은 부분적/전체적으로 이루어진다

조정횟수, 조정량은 변동성 관련 지표로 사용할 수 있을듯 하다
2016/6/27 웨어하우스 J에서 Product_613의 오더수량이 10회 입력되었고 그 중 1회는 감소에 관한 것이었다

2016/6/27 웨어하우스 J에서 Product_1157 오더수량이 3회 입력되었고 두 번의 감소 조정을 통해 결과적으로 오더가 취소되었다

당일 Order Demand 합계가 음수는 무엇을 의미하는가?
알 수 없다
print(df[(df['Date']>datetime.date(2011,10,1)) & (df['Date']<datetime.date(2011,10,30))& (df['Warehouse'] == 'S') & (df['Product_Code'] == 125)])

TO-DOs
데이터 시각화
시간에 따른 데이터 시각화, Order Demand 음수 데이터 관찰
결측치 처리, 중복 데이터 처리

 

728x90