출처 : https://dacon.io/competitions/official/235743/overview/description

1. 분석 배경 및 목적

  • 분석 배경

지금까지는 단순한 시계열 추세와 담당자의 직관적 경험에 의존하여 한국토지주택공사 구내식당 식수 인원을 예측하였으나, 빅데이터 분석으로 얻어지는 보다 정확도 높은 예측을 통해 잔반 발생량을 획기적으로 줄이고자 함.

  • 목적

구내식당의 요일별 점심, 저녁식사를 먹는 인원 예측

2. 라이브러리 및 데이터 불러오기

# 라이브러리 로드

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import koreanize_matplotlib
# 데이터 로드
train = pd.read_csv("data/train.csv", parse_dates=["일자"])
train.head()
일자 요일 본사정원수 본사휴가자수 본사출장자수 본사시간외근무명령서승인건수 현본사소속재택근무자수 조식메뉴 중식메뉴 석식메뉴 중식계 석식계
0 2016-02-01 2601 50 150 238 0.0 모닝롤/찐빵 우유/두유/주스 계란후라이 호두죽/쌀밥 (쌀:국내산) 된장찌개 쥐... 쌀밥/잡곡밥 (쌀,현미흑미:국내산) 오징어찌개 쇠불고기 (쇠고기:호주산) 계란찜 ... 쌀밥/잡곡밥 (쌀,현미흑미:국내산) 육개장 자반고등어구이 두부조림 건파래무침 ... 1039.0 331.0
1 2016-02-02 2601 50 173 319 0.0 모닝롤/단호박샌드 우유/두유/주스 계란후라이 팥죽/쌀밥 (쌀:국내산) 호박젓국찌... 쌀밥/잡곡밥 (쌀,현미흑미:국내산) 김치찌개 가자미튀김 모둠소세지구이 마늘쫑무... 콩나물밥*양념장 (쌀,현미흑미:국내산) 어묵국 유산슬 (쇠고기:호주산) 아삭고추무... 867.0 560.0
2 2016-02-03 2601 56 180 111 0.0 모닝롤/베이글 우유/두유/주스 계란후라이 표고버섯죽/쌀밥 (쌀:국내산) 콩나물국... 카레덮밥 (쌀,현미흑미:국내산) 팽이장국 치킨핑거 (닭고기:국내산) 쫄면야채무침 ... 쌀밥/잡곡밥 (쌀,현미흑미:국내산) 청국장찌개 황태양념구이 (황태:러시아산) 고기... 1017.0 573.0
3 2016-02-04 2601 104 220 355 0.0 모닝롤/토마토샌드 우유/두유/주스 계란후라이 닭죽/쌀밥 (쌀,닭:국내산) 근대국... 쌀밥/잡곡밥 (쌀,현미흑미:국내산) 쇠고기무국 주꾸미볶음 부추전 시금치나물 ... 미니김밥*겨자장 (쌀,현미흑미:국내산) 우동 멕시칸샐러드 군고구마 무피클 포... 978.0 525.0
4 2016-02-05 2601 278 181 34 0.0 모닝롤/와플 우유/두유/주스 계란후라이 쇠고기죽/쌀밥 (쌀:국내산) 재첩국 방... 쌀밥/잡곡밥 (쌀,현미흑미:국내산) 떡국 돈육씨앗강정 (돼지고기:국내산) 우엉잡채... 쌀밥/잡곡밥 (쌀,현미흑미:국내산) 차돌박이찌개 (쇠고기:호주산) 닭갈비 (닭고기:... 925.0 330.0
test = pd.read_csv("data/test.csv", parse_dates=["일자"])
test.head()
일자 요일 본사정원수 본사휴가자수 본사출장자수 본사시간외근무명령서승인건수 현본사소속재택근무자수 조식메뉴 중식메뉴 석식메뉴
0 2021-01-27 2983 88 182 5 358.0 모닝롤/연유버터베이글 우유/주스 계란후라이/찐계란 단호박죽/흑미밥 우거지국 고기완자... 쌀밥/흑미밥/찰현미밥 대구지리 매운돈갈비찜 오꼬노미계란말이 상추무침 포기김치 양상추... 흑미밥 얼큰순두부찌개 쇠고기우엉볶음 버섯햄볶음 (New)아삭이고추무절임 포기김치
1 2021-01-28 2983 104 212 409 348.0 모닝롤/대만샌드위치 우유/주스 계란후라이/찐계란 누룽지탕/흑미밥 황태국 시래기지짐 ... 쌀밥/보리밥/찰현미밥 우렁된장찌개 오리주물럭 청양부추전 수제삼색무쌈 겉절이김치 양상... 충무김밥 우동국물 오징어무침 꽃맛살샐러드 얼갈이쌈장무침 석박지
2 2021-01-29 2983 270 249 0 294.0 모닝롤/핫케익 우유/주스 계란후라이/찐계란 오곡죽/흑미밥 매생이굴국 고구마순볶음 양... 쌀밥/흑미밥/찰현미밥 팽이장국 수제돈까스*소스 가자미조림 동초나물무침 포기김치 양상... 흑미밥 물만둣국 카레찜닭 숯불양념꼬지어묵 꼬시래기무침 포기김치
3 2021-02-01 2924 108 154 538 322.0 모닝롤/촉촉한치즈케익 우유/주스 계란후라이/찐계란 누룽지탕/흑미밥 두부김칫국 새우완... 쌀밥/흑미밥/찰현미밥 배추들깨국 오리대패불고기 시금치프리타타 부추고추장무침 포기김치... 흑미밥 동태탕 돈육꽈리고추장조림 당면채소무침 모자반무침 포기김치
4 2021-02-02 2924 62 186 455 314.0 모닝롤/토마토샌드 우유/주스 계란후라이/찐계란 채소죽/흑미밥 호박맑은국 오이생채 양... 쌀밥/팥밥/찰현미밥 부대찌개 닭살데리야끼조림 버섯탕수 세발나물무침 알타리김치/사과푸... 흑미밥 바지락살국 쇠고기청경채볶음 두부구이*볶은김치 머위된장무침 백김치

3. 데이터 파악 및 전처리

# 결측치 확인
train.isnull().sum()
일자                0
요일                0
본사정원수             0
본사휴가자수            0
본사출장자수            0
본사시간외근무명령서승인건수    0
현본사소속재택근무자수       0
조식메뉴              0
중식메뉴              0
석식메뉴              0
중식계               0
석식계               0
dtype: int64
test.isnull().sum()
일자                0
요일                0
본사정원수             0
본사휴가자수            0
본사출장자수            0
본사시간외근무명령서승인건수    0
현본사소속재택근무자수       0
조식메뉴              0
중식메뉴              0
석식메뉴              0
dtype: int64
# 중복값 확인
train[train.duplicated()]
일자 요일 본사정원수 본사휴가자수 본사출장자수 본사시간외근무명령서승인건수 현본사소속재택근무자수 조식메뉴 중식메뉴 석식메뉴 중식계 석식계
# info 확인
train.info(), test.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1205 entries, 0 to 1204
Data columns (total 12 columns):
 #   Column          Non-Null Count  Dtype         
---  ------          --------------  -----         
 0   일자              1205 non-null   datetime64[ns]
 1   요일              1205 non-null   object        
 2   본사정원수           1205 non-null   int64         
 3   본사휴가자수          1205 non-null   int64         
 4   본사출장자수          1205 non-null   int64         
 5   본사시간외근무명령서승인건수  1205 non-null   int64         
 6   현본사소속재택근무자수     1205 non-null   float64       
 7   조식메뉴            1205 non-null   object        
 8   중식메뉴            1205 non-null   object        
 9   석식메뉴            1205 non-null   object        
 10  중식계             1205 non-null   float64       
 11  석식계             1205 non-null   float64       
dtypes: datetime64[ns](1), float64(3), int64(4), object(4)
memory usage: 113.1+ KB
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 50 entries, 0 to 49
Data columns (total 10 columns):
 #   Column          Non-Null Count  Dtype         
---  ------          --------------  -----         
 0   일자              50 non-null     datetime64[ns]
 1   요일              50 non-null     object        
 2   본사정원수           50 non-null     int64         
 3   본사휴가자수          50 non-null     int64         
 4   본사출장자수          50 non-null     int64         
 5   본사시간외근무명령서승인건수  50 non-null     int64         
 6   현본사소속재택근무자수     50 non-null     float64       
 7   조식메뉴            50 non-null     object        
 8   중식메뉴            50 non-null     object        
 9   석식메뉴            50 non-null     object        
dtypes: datetime64[ns](1), float64(1), int64(4), object(4)
memory usage: 4.0+ KB





(None, None)
# describe 확인
train.describe()
본사정원수 본사휴가자수 본사출장자수 본사시간외근무명령서승인건수 현본사소속재택근무자수 중식계 석식계
count 1205.000000 1205.000000 1205.000000 1205.000000 1205.000000 1205.000000 1205.000000
mean 2807.815768 157.913693 241.142739 274.117012 43.506224 890.334440 461.772614
std 171.264404 144.190572 43.532298 246.239651 109.937400 209.505057 139.179202
min 2601.000000 23.000000 41.000000 0.000000 0.000000 296.000000 0.000000
25% 2645.000000 71.000000 217.000000 4.000000 0.000000 758.000000 406.000000
50% 2760.000000 105.000000 245.000000 299.000000 0.000000 879.000000 483.000000
75% 2962.000000 185.000000 272.000000 452.000000 0.000000 1032.000000 545.000000
max 3305.000000 1224.000000 378.000000 1044.000000 533.000000 1459.000000 905.000000
train.describe(include="object")
요일 조식메뉴 중식메뉴 석식메뉴
count 1205 1205 1205 1205
unique 5 1204 1198 1168
top 모닝롤/프렌치토스트 우유/주스 계란후라이 누룽지탕/쌀밥 (쌀:국내산) 무채국 김... 쌀밥/잡곡밥 (쌀:국내산) 시금치된장국 훈제오리구이 실곤약무침 무쌈/양파절임 ... *
freq 244 2 2 19
test.describe()
본사정원수 본사휴가자수 본사출장자수 본사시간외근무명령서승인건수 현본사소속재택근무자수
count 50.000000 50.000000 50.000000 50.000000 50.000000
mean 2956.840000 129.520000 209.220000 380.140000 298.140000
std 24.968846 84.065873 39.454593 346.564304 52.058056
min 2924.000000 50.000000 131.000000 0.000000 179.000000
25% 2924.000000 78.250000 176.500000 1.000000 257.250000
50% 2974.000000 95.000000 202.500000 465.500000 300.000000
75% 2975.000000 137.500000 245.250000 681.000000 333.250000
max 2983.000000 489.000000 279.000000 1003.000000 413.000000
test.describe(include="object")
요일 조식메뉴 중식메뉴 석식메뉴
count 50 50 50 50
unique 5 50 50 50
top 모닝롤/연유버터베이글 우유/주스 계란후라이/찐계란 단호박죽/흑미밥 우거지국 고기완자... 쌀밥/흑미밥/찰현미밥 대구지리 매운돈갈비찜 오꼬노미계란말이 상추무침 포기김치 양상추... 흑미밥 얼큰순두부찌개 쇠고기우엉볶음 버섯햄볶음 (New)아삭이고추무절임 포기김치
freq 11 1 1 1
# 컬럼명 변경
train_cols=["일자","요일","전체","휴가","출장","시간외근무", "재택근무", "조식","중식","석식","중식계","석식계"]
train.columns = train_cols
test_cols=["일자","요일","전체","휴가","출장","시간외근무", "재택근무", "조식","중식","석식"]
test.columns = test_cols
# 조식 컬럼 제외
train = train.drop(columns=["조식"])
test = test.drop(columns=["조식"])
# 요일을 숫자로 바꾸기
train['요일'] = train['요일'].map({'월':1, '화':2, '수':3, '목':4, '금':5})
test['요일'] = test['요일'].map({'월':1, '화':2, '수':3, '목':4, '금':5})
# 날짜를 월, 일 컬럼으로 

train['월'] = pd.DatetimeIndex(train['일자']).month
test['월'] = pd.DatetimeIndex(test['일자']).month
train['일'] = pd.DatetimeIndex(train['일자']).day
test['일'] = pd.DatetimeIndex(test['일자']).day
# 상관관계
train_corr = train.corr()
# 상관관계 히트맵

mask = np.triu(np.ones_like(train_corr))
sns.heatmap(train_corr, annot=True, fmt=".2f", mask = mask, cmap="coolwarm",vmin=-1,vmax=1);

# 메뉴 전처리
# 밥, 반찬과 그 외로 인코딩
train["중식_밥반찬"] = (train["중식"].map(lambda x : x.split("/")[0]).str.contains("쌀밥|흑미밥|잡곡밥", regex=True)).astype(int)
train["중식_밥반찬"].value_counts()
1    1006
0     199
Name: 중식_밥반찬, dtype: int64
test["중식_밥반찬"] = (test["중식"].map(lambda x : x.split("/")[0]).str.contains("쌀밥|흑미밥|잡곡밥", regex=True)).astype(int)
test["중식_밥반찬"].value_counts()
1    48
0     2
Name: 중식_밥반찬, dtype: int64
train["석식_밥반찬"] = (train["석식"].map(lambda x : x.split("/")[0]).str.contains("쌀밥|흑미밥|잡곡밥", regex=True)).astype(int)
train["석식_밥반찬"].value_counts()
1    755
0    450
Name: 석식_밥반찬, dtype: int64
test["석식_밥반찬"] = (test["석식"].map(lambda x : x.split("/")[0]).str.contains("쌀밥|흑미밥|잡곡밥", regex=True)).astype(int)
test["석식_밥반찬"].value_counts()
1    36
0    14
Name: 석식_밥반찬, dtype: int64
# 출근 파생 변수 생성
train["출근"] = train["전체"] - train["휴가"] - train["재택근무"] - train["출장"]
test["출근"] = test["전체"] - test["휴가"] - test["재택근무"]- test["출장"]

중식계 예측 train data

train[train["중식계"]==0]
일자 요일 전체 휴가 출장 시간외근무 재택근무 중식 석식 중식계 석식계 중식_밥반찬 석식_밥반찬 출근
  • 중식계에는 0인 데이터가 없어 train 데이터 그대로 사용

석식계 예측 train data

train[train["석식계"]==0]
일자 요일 전체 휴가 출장 시간외근무 재택근무 중식 석식 중식계 석식계 중식_밥반찬 석식_밥반찬 출근
204 2016-11-30 3 2689 68 207 0 0.0 나물비빔밥 (쌀:국내산) 가쯔오장국 치킨핑거*요거트D 감자샐러드 오복지무침 ... * 1109.0 0.0 11 30 0 0 2414.0
224 2016-12-28 3 2705 166 225 0 0.0 콩나물밥 (쌀:국내산) 가쯔오장국 미트볼케찹조림 꽃맛살샐러드 군고구마 배추겉... * 767.0 0.0 12 28 0 0 2314.0
244 2017-01-25 3 2697 79 203 0 0.0 카레덮밥 (쌀:국내산) 맑은국 유린기 개성감자만두 오이사과무침 포기김치 (김... * 720.0 0.0 1 25 0 0 2415.0
262 2017-02-22 3 2632 75 252 0 0.0 나물비빔밥 (쌀:국내산) 유부장국 생선까스*탈탈소스 파스타샐러드 마늘쫑볶음 ... * 1065.0 0.0 2 22 0 0 2305.0
281 2017-03-22 3 2627 53 235 0 0.0 쌀밥/잡곡밥 (쌀:국내산) 돈육김치찌개 유린기 비엔나볶음 세발나물 깍두기 (... * 953.0 0.0 3 22 1 0 2339.0
306 2017-04-26 3 2626 45 304 0 0.0 비빔밥 (쌀:국내산) 맑은국 오징어튀김 견과류조림 하와이안샐러드 깍두기 (김... * 835.0 0.0 4 26 0 0 2277.0
327 2017-05-31 3 2637 43 265 0 0.0 열무보리비빔밥 (쌀:국내산) 가쯔오장국 탕수만두 콥샐러드 오이지무침 포기김치... 자기계발의날 910.0 0.0 5 31 0 0 2329.0
346 2017-06-28 3 2648 58 259 0 0.0 콩나물밥 (쌀:국내산) 얼갈이된장국 삼치구이 잡채 아삭고추무침 깍두기 (김치... *자기계발의날* 745.0 0.0 6 28 0 0 2331.0
366 2017-07-26 3 2839 254 246 0 0.0 나물비빔밥 미소장국 파스타샐러드 소세지오븐구이 오렌지 포기김치 (김치:국내산) 가정의날 797.0 0.0 7 26 0 0 2339.0
392 2017-09-01 5 2642 177 303 45 0.0 쌀밥/잡곡밥 (쌀:국내산) 시래기국 훈제오리구이 두부구이*양념장 쌈무/양파절임... * 663.0 0.0 9 1 1 0 2162.0
410 2017-09-27 3 2642 70 265 0 0.0 쌀밥/잡곡밥 (쌀:국내산) 콩나물국 삼겹살구이 어묵볶음 상추파무침 포기김치 ... 쌀밥/잡곡밥 (쌀:국내산) 된장찌개 미니함박조림 계란말이 비름나물 포기김치 ... 1023.0 0.0 9 27 1 1 2307.0
412 2017-09-29 5 2642 214 248 22 0.0 쌀밥/잡곡밥 (쌀:국내산) 미역국 쇠불고기/잡채 오징어숙회무침 미니케익/식혜 ... * 760.0 0.0 9 29 1 0 2180.0
424 2017-10-25 3 2645 75 289 0 0.0 곤드레밥*강된장 (쌀:국내산) 가쯔오장국 갈치조림 쇠고기잡채 쑥갓두부무침 알... * 786.0 0.0 10 25 0 0 2281.0
449 2017-11-29 3 2644 78 261 0 0.0 나물비빔밥 (쌀:국내산) 미소장국 코다리조림 과일샐러드 군고구마 깍두기 (김... * 903.0 0.0 11 29 0 0 2305.0
468 2017-12-27 3 2665 169 255 0 0.0 쌀밥/잡곡밥 (쌀:국내산) 쇠고기미역국 오징어볶음 동그랑땡전 무쌈말이 포기김... * 571.0 0.0 12 27 1 0 2241.0
492 2018-01-31 3 2655 56 223 0 0.0 김치제육덮밥 미소장국 양장피잡채 계란찜 아삭고추무침/귤 알타리김치 (김치:... * 1138.0 0.0 1 31 0 0 2376.0
502 2018-02-14 3 2707 418 159 0 0.0 쌀밥/잡곡밥 (쌀:국내산) 떡국 버섯불고기 오징어숙회무침 취나물 배추겉절이 ... 쌀밥/잡곡밥 (쌀:국내산) 쇠고기무국 고추잡채*꽃빵 계란찜 오이무침 포기김치... 850.0 0.0 2 14 1 1 2130.0
510 2018-02-28 3 2707 134 278 0 0.0 곤드레밥*강된장 (쌀:국내산) 어묵국 치킨핑거*요거트소스 도토리묵무침 콩조림 ... * 786.0 0.0 2 28 0 0 2295.0
529 2018-03-28 3 2714 45 252 0 0.0 단호박카레라이스 (쌀:국내산) 유부장국 유린기 볼어묵볶음 오복지 포기김치 (... * 926.0 0.0 3 28 0 0 2417.0
549 2018-04-25 3 2714 66 285 0 0.0 비빔밥 (쌀:국내산) 유부장국 오징어튀김 떡밤초 요플레 포기김치 (김치:국내산) 851.0 0.0 4 25 0 0 2363.0
571 2018-05-30 3 2721 80 281 0 0.0 콩나물밥 (쌀:국내산) 유부장국 수제돈가스 파스타샐러드 무생채 포기김치 (김... 876.0 0.0 5 30 0 0 2360.0
589 2018-06-27 3 2728 66 277 0 0.0 카레덮밥 (쌀:국내산) 가쯔오장국 깐풍육 구운채소 *발사믹소스 오복지무침 포기... * 957.0 0.0 6 27 0 0 2385.0
609 2018-07-25 3 2704 226 256 1 0.0 쌀밥/잡곡밥 (쌀:국내산) 쇠고기샤브국 유린기 사각어묵볶음 오이사과생채 포기... 760.0 0.0 7 25 1 0 2222.0
633 2018-08-29 3 2996 103 258 0 0.0 콩나물밥 (쌀:국내산) 팽이장국 치킨핑거 메추리알조림 과일샐러드 배추겉절이 ... * 915.0 0.0 8 29 0 0 2635.0
648 2018-09-19 3 2763 77 288 0 0.0 카레덮밥 (쌀:국내산) 유부장국 감자프리타타 메밀전병만두 쨔샤이무침/과일 포... 833.0 0.0 9 19 0 0 2398.0
667 2018-10-31 3 2805 111 306 0 0.0 쌀밥/잡곡밥 (쌀:국내산) 콩나물국 수제돈가스 닭살겨자채 반달호박나물 포기김... 자기계발의날 930.0 0.0 10 31 1 0 2388.0
687 2018-11-28 3 2815 69 298 1 0.0 나물비빔밥 (쌀:국내산) 가쯔오장국 오징어튀김 (오징어:뉴질랜드) 과일샐러드 군... * 862.0 0.0 11 28 0 0 2448.0
706 2018-12-26 3 2846 184 241 0 0.0 쌀밥/잡곡밥 (쌀:국내산) 아욱국 돈육굴소스볶음 골뱅이무침*소면 얼갈이나물 ... 자기계발의날 695.0 0.0 12 26 1 0 2421.0
730 2019-01-30 3 2985 66 226 1 0.0 카레덮밥 (쌀:국내산,돈육:국내산) 유부장국 새우까스*칠리소스 쫄면무침 오이무... 자기개발의날 679.0 0.0 1 30 0 0 2693.0
747 2019-02-27 3 2806 100 274 0 0.0 비빔밥 (쌀:국내산) 유부장국 오징어튀김 떡밤초 음료 포기김치 (김치:국내산) * 자기계발의날 * 944.0 0.0 2 27 0 0 2432.0
766 2019-03-27 3 2836 92 259 0 0.0 단호박영양밥 (쌀:국내산) 가쯔오장국 돈육칠리강정 모듬묵샐러드 숙주나물 배추... * 자기개발의날 * 856.0 0.0 3 27 0 0 2485.0
786 2019-04-24 3 2822 59 273 0 0.0 카레라이스 (쌀:국내산) 미소장국 언양식불고기 떡볶이 방울토마토 포기김치 (... * 자기계발의날 * 1034.0 0.0 4 24 0 0 2490.0
809 2019-05-29 3 2825 50 237 0 0.0 쌀밥/잡곡밥 (쌀:국내산) 배추된장국 수제돈가스 마파두부 돈나물유자청무침 포... * 자기개발의날 * 896.0 0.0 5 29 1 0 2538.0
828 2019-06-26 3 2758 69 282 0 0.0 카레덮밥 (쌀,돈육:국내산) 가쯔오장국 고구마치즈구이 쫄면무침 무말랭이 포기... * 자기개발의날 * 946.0 0.0 6 26 0 0 2407.0
853 2019-07-31 3 2760 495 231 0 0.0 곤드레밥*양념장 (쌀:국내산) 맑은국 해물누룽지탕 (오징어:원양산) 메밀전병만두 ... 자기계발의날 619.0 0.0 7 31 0 0 2034.0
872 2019-08-28 3 3305 123 274 0 0.0 카레덮밥 (쌀,돈육:국내산) 맑은국 치킨핑거 (닭:국내산) 쫄면야채무침 오복지/... * 899.0 0.0 8 28 0 0 2908.0
890 2019-09-25 3 3111 60 285 1 0.0 곤드레밥*양념장 (쌀:국내산) 맑은국 돈육강정 (돈육:국내산) 사과고구마그라탕 ... * 803.0 0.0 9 25 0 0 2766.0
912 2019-10-30 3 3121 122 294 1 0.0 마파두부덮밥 (쌀,돈육:국내산) 맑은국 치킨핑거 (닭:국내산) 시저샐러드 무비트... * 771.0 0.0 10 30 0 0 2705.0
932 2019-11-27 3 3104 134 288 1 0.0 나물비빔밥 (쌀:국내산) 맑은국 감자치즈구이 군만두 치커리유자청생채 포기김치... * 732.0 0.0 11 27 0 0 2682.0
955 2019-12-31 2 3111 709 149 22 0.0 쌀밥/잡곡밥 (쌀:국내산) 배추된장국 닭볶음탕 (닭:국내산) 부추깻잎전 양배추쌈... * 349.0 0.0 12 31 1 0 2253.0
973 2020-01-29 3 2821 101 214 4 0.0 콩나물밥*양념장 (쌀:국내산,소고기:호주) 가쯔오장국 치킨핑거 (닭:국내산) 꽃맛... 자기개발의날 1197.0 0.0 1 29 0 0 2506.0
993 2020-02-26 3 2872 109 190 4 0.0 낙지비빔밥 (쌀:국내,낙지:중국산) 팽이장국 치킨텐더*콘소스D (닭:국내산) 과일... 자기개발의날 1105.0 0.0 2 26 0 0 2573.0
1166 2020-11-25 3 3021 206 191 3 387.0 쌀밥/흑미밥/찰현미밥 콩비지김치찌개 해물누룽지탕 탕평채 고추장감자조림 깍두기/수제과... <자기 계발의 날> 1146.0 0.0 11 25 1 0 2237.0
train[train["석식계"]==0]["요일"].value_counts()
3    40
5     2
2     1
Name: 요일, dtype: int64
  • 석식계에는 0인 데이터가 존재, 대체로 달의 마지막 주 수요일에 해당

  • 마지막 주 수요일의 석식계 평균값으로 대치

# 마지막주 수요일의 석식계 평균으로 대체
dinner_nan = train.loc[(train["요일"] == 2) & (train["일"].isin(range(24,32))), "석식계"].replace(0, np.nan).mean()
dinner_nan
522.8983050847457
train.loc[train["석식계"]==0,"석식계"]=dinner_nan
train[train["석식계"]==0]
일자 요일 전체 휴가 출장 시간외근무 재택근무 중식 석식 중식계 석식계 중식_밥반찬 석식_밥반찬 출근
  • 식단이 있으나 석식계가 0인 2개 행은 제거
no = train[(train["석식계"]==0) & (train["석식"].map(lambda x : x.split("/")[0]).str.contains("쌀밥|흑미밥|잡곡밥",regex=True))].index
train_dinner = train.drop(no)
plt.figure(figsize=(10,5))
sns.lineplot(data=train, x="일자", y="전체");

plt.figure(figsize=(10,1))
sns.boxplot(data=train, x="시간외근무");

plt.figure(figsize=(10,3))
sns.stripplot(data=train, x="시간외근무");

plt.figure(figsize=(10,3))
sns.stripplot(data=train, x="재택근무");

plt.figure(figsize=(5, 2))
sns.barplot(data=train, x="요일", y="출장", errorbar=None);

plt.figure(figsize=(5, 2))
sns.barplot(data=train, x="요일", y="시간외근무",errorbar=None);

plt.figure(figsize=(5, 2))
sns.barplot(data=train, x='요일', y='중식계',errorbar=None);

plt.figure(figsize=(5, 2))
sns.barplot(data=train, x='요일', y='석식계',errorbar=None);

df = train[["요일","중식계","석식계"]]
df.corr()
요일 중식계 석식계
요일 1.000000 -0.731563 -0.396205
중식계 -0.731563 1.000000 0.633010
석식계 -0.396205 0.633010 1.000000
fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (20, 10))
sns.histplot(train["중식계"], ax = ax[0])
sns.histplot(train["석식계"], ax = ax[1])
plt.show()

plt.figure(figsize=(5, 2))
sns.barplot(data=train, x='요일', y='휴가',errorbar=None);

plt.figure(figsize=(5, 2))
sns.barplot(data=train, x='요일', y='재택근무',errorbar=None);

plt.figure(figsize=(5, 2))
sns.barplot(data=train, x='요일', y='출장',errorbar=None);

4. 학습, 예측 데이터셋 구성

label_name1 = "중식계"
label_name2= "석식계"
train.columns
Index(['일자', '요일', '전체', '휴가', '출장', '시간외근무', '재택근무', '중식', '석식', '중식계', '석식계',
       '월', '일', '중식_밥반찬', '석식_밥반찬', '출근'],
      dtype='object')
feature_names1=["요일", "시간외근무","출근","중식_밥반찬","월","일"] 
feature_names2=["요일", "시간외근무","출근","석식_밥반찬","월","일"]

중식계 train data

X_train1 = train[feature_names1]
display(X_train1.head(2))
X_train1.shape
요일 시간외근무 출근 중식_밥반찬
0 1 238 2401.0 1 2 1
1 2 319 2378.0 1 2 2
(1205, 6)
y_train1 = train[label_name1]
y_train1.shape
(1205,)
X_test1 = test[feature_names1]
X_test1.shape
(50, 6)

석식계 train data

X_train2 = train_dinner[feature_names2]
display(X_train2.head(2))
X_train2.shape
요일 시간외근무 출근 석식_밥반찬
0 1 238 2401.0 1 2 1
1 2 319 2378.0 0 2 2
(1205, 6)
y_train2 = train_dinner[label_name2]
y_train2.shape
(1205,)
X_test2 = test[feature_names2]
X_test2.shape
(50, 6)

5. 머신러닝 알고리즘

중식계 예측

from sklearn.ensemble import RandomForestRegressor
model1 = RandomForestRegressor(n_estimators=100, n_jobs=-1, criterion="absolute_error", random_state=42)
model1
RandomForestRegressor(criterion='absolute_error', n_jobs=-1, random_state=42)
model1.fit(X_train1, y_train1)
RandomForestRegressor(criterion='absolute_error', n_jobs=-1, random_state=42)
from sklearn.model_selection import cross_val_predict

y_predict1 = cross_val_predict(model1, X_train1, y_train1, cv=5, n_jobs=-1)
from sklearn.metrics import r2_score

r2_score(y_train1, y_predict1)
0.6551438143397688
y_predict1 = model1.predict(X_test1)
y_predict1
array([ 903.56 ,  923.11 ,  653.55 , 1204.23 , 1021.93 , 1005.78 ,
       1020.57 ,  790.28 , 1273.66 , 1017.39 ,  924.57 , 1260.055,
       1068.435,  938.81 ,  947.1  ,  675.63 , 1266.505, 1093.24 ,
       1000.47 ,  959.16 ,  675.92 , 1073.07 , 1038.59 , 1007.92 ,
        623.18 , 1310.545, 1094.41 ,  968.985,  966.19 ,  710.47 ,
       1278.36 ,  999.255,  985.165,  934.51 ,  685.76 , 1229.19 ,
       1005.535,  960.465,  934.91 ,  661.76 , 1266.49 , 1022.93 ,
       1044.45 ,  878.9  ,  717.55 , 1187.77 , 1001.495,  952.75 ,
        910.37 ,  725.09 ])
y_predict1 = y_predict1.tolist()

석식계 예측

model2 = RandomForestRegressor(n_estimators=100, n_jobs=-1, criterion="absolute_error",random_state=42)
model2
RandomForestRegressor(criterion='absolute_error', n_jobs=-1, random_state=42)
model2.fit(X_train2, y_train2)
RandomForestRegressor(criterion='absolute_error', n_jobs=-1, random_state=42)
y_predict2 = cross_val_predict(model2, X_train2, y_train2, cv=5, n_jobs=-1)
r2_score(y_train2, y_predict2)
0.3957326052969119
y_predict2 = model2.predict(X_test2)
y_predict2
array([370.84      , 506.93      , 265.81      , 556.54      ,
       547.1       , 514.01491525, 500.88      , 419.48389831,
       689.41      , 584.6       , 443.64949153, 709.94      ,
       728.09      , 503.43940678, 562.2       , 373.11898305,
       740.32      , 696.74      , 478.09101695, 558.47      ,
       377.27      , 710.47      , 475.25      , 608.1       ,
       397.94288136, 748.72      , 747.96      , 459.18      ,
       626.03      , 391.06898305, 741.47      , 647.        ,
       475.30694915, 550.73      , 356.72      , 656.53      ,
       660.26      , 508.68898305, 506.67      , 336.27      ,
       650.3       , 643.26      , 460.37898305, 498.89      ,
       362.6       , 616.12      , 633.78      , 495.83694915,
       495.75      , 376.74      ])
y_predict2 = y_predict2.tolist()

제출

submit = pd.read_csv("data/sample_submission.csv")
submit.head(2)
일자 중식계 석식계
0 2021-01-27 0 0
1 2021-01-28 0 0
submit["중식계"] = y_predict1
submit["석식계"] = y_predict2
submit.head(2)
일자 중식계 석식계
0 2021-01-27 903.56 370.84
1 2021-01-28 923.11 506.93
submit.to_csv("data/submit_1.csv", index=False)
pd.read_csv("data/submit_1.csv").head()
일자 중식계 석식계
0 2021-01-27 903.56 370.84
1 2021-01-28 923.11 506.93
2 2021-01-29 653.55 265.81
3 2021-02-01 1204.23 556.54
4 2021-02-02 1021.93 547.10