구내식당 식수 인원 예측 AI 경진대회 알고리즘
출처 : 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 |