#4 가게 매출 예측

회귀를 공부하고 분류 강의가 나올 때까지 기다리고 있는 상황에서
딥러닝 강의도 회귀까지 정리했고 할 것이 마땅치 않아
선형 회귀 실습을 해봐야겠다고 생각했다.
데이터를 찾다가 공공 데이터도 있겠지만 어머니 가게 매출 데이터를 뽑아서 해봐야겠다고 생각했다.

하지만 가게 포스 기계에서는 매출만 txt로 뽑을 수 있고
메뉴별 매출이나 시간대별 매출은 제공되지 않는 것 같았다.
그래서 내가 여러 변수를 만들기로 했다.

우선 매출은 데이터로 뽑아 왔고,
매출에 영향을 줄 수 있는 요인은 무엇이 있나 생각해보았다.
날씨도 영향을 줄 것 같고
학교 앞이라 방학 여부도 중요할 것 같았다.
그리고 중요하다고 생각한 것은 요일이었다.

그래서 날씨 데이터를 인터넷에서 뽑고
방학 여부는 1,2,7,8 월 달은 방학이라는 표시를 했다.
요일은 파이썬의 datetime 모듈을 사용했다.

매출 데이터는 2013년 부터 2016년까지 사용했다.
아래의 코드를 사용해 매출 데이터를 예측해봤다.
-----------------------------------------------------------------------
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
import time
from sklearn import linear_model
from sklearn import cross_validation

def order_data():
    f = open("샤브향_정산분석파일.txt")
    sales = []
    count = 0
    for line in f.readlines():
        if line[-1] == '\n':
            sales.append(line[:-1])
        count =count + 1
    data = []
    count_min = 0
    count_max = int((count - 4)/2)

    for i in range(count_min,count_max):
        data.append(sales[2*i+4])

    data = np.asarray(data)
    Rdata = []
    date = []
    sales_record = []

    for i in range(len(data)-2):
        Rdata.append(data[i][1:-1])
        date.append(Rdata[i][:10])
        Sdata = Rdata[i][-10:].strip()
        sales_record.append(Sdata.replace(',',''))
 
    date = np.asarray(date)
    date = pd.to_datetime(date)
    sales_record = np.asarray(sales_record)

    return date,sales_record

def make_dataframe(date, sales):
    dic = {'date' : date , 'sales' : sales, 'weekday' : date.weekday}
    df = pd.DataFrame(data = dic, columns=['sales','weekday'])
    df.sales = df.sales.astype(int)
    df.index = pd.Index(date)
    return df

def cut_data(dataframe):
    dataframe = dataframe.sort(['sales'], ascending=[0])
    num = int(len(dataframe)*0.2)
    dataframe_high = dataframe[:num]
    dataframe_low = dataframe[-num :]
    return dataframe_high,dataframe_low

def divide_set(df):
    vacation = []
    semester = []
    for period in ['2013','2014','2015','2016']:
        for i in range(1,13):
            string = '-' + str(i)
            if string == '-1' or string == '-2' or string == '-7' or string == '-8':
                try:
                    vacation.append(df[period+string])
                except:
                    continue
            else:
                try:
                    semester.append(df[period+string])
                except:
                    continue
    vacation = pd.concat(vacation)
    semester = pd.concat(semester)
    return vacation,semester

def cut_data(dataframe):
    dataframe = dataframe.sort_values(by='sales', ascending=[0])
    num = int(len(dataframe)*0.2)
    dataframe_high = dataframe[:num]
    dataframe_low = dataframe[-num :]
    return dataframe_high,dataframe_low

def load_weather():
    text = open('이천평균기온.txt')
    res = []
 
    for line in text.readlines():
        line = line.strip().split('\t')
        res.append(line)
 
    num = int(len(res)/4)
    fst = res[:num]
    snd = res[num:2*num]
    thd = res[2*num:3*num]
    fth = res[3*num:]
 
    return fst,snd,thd,fth
 
def col_data(data,num):
    res = []
    try:
        for j in data[1:]:
            res.append(j[num])
    except:
        pass
    return res
 
def merge_data(data):
    month = data[0]
    res = []

    for i in range(1 , len(month)+1):
        res.extend(col_data(data,i))

    return res
 
def weather_df(weather,date):
    start = '2013-3-22'
    end = '2016-3-22'
    period = pd.date_range(start,end,freq='D')
 
    dic = {'date' : period , 'weather' : weather}
    df = pd.DataFrame(data = dic , columns=['weather'])
    df.index = pd.Index(period)
    df = df.drop(period.difference(date))
 
    return df

if __name__ == "__main__":
    date, sales = order_data()
    df = make_dataframe(date,sales)
    fst,snd,thd,fth = load_weather()

    weather = []
    for data in [fst,snd,thd,fth]:
        tmp = merge_data(data)
        weather.extend(tmp)
    weather = [float(a) for a in weather if not  a == '' and not  a == ' ']
    weatherDF = weather_df(weather,date)
    df['temp'] = weatherDF.weather

    vacation,semester = divide_set(df)
    vacation['vacation'] = 1
    semester['vacation'] = 0
    vacation_high,vacation_low = cut_data(vacation)
    semester_high,semester_low = cut_data(semester)

    df = pd.concat([vacation,semester])
    df = df.sort_index()

    sales_high,sales_low = cut_data(df)

    data = df.copy()
    data = data.dropna()
    target = data.sales
    del data['sales']

    X_train, X_test, y_train, y_test = cross_validation.train_test_split(data, target, test_size=0.25, random_state=0)
    clf = linear_model.Lasso(alpha= 0.01,normalize=True)
    clf.fit(X_train,y_train)

    print('Coefficients: \n', clf.coef_)
    # The mean square error
    print("Residual sum of squares: %.2f"
          % np.mean((clf.predict(X_test) - y_test) ** 2))
    # Explained variance score: 1 is perfect prediction
    print('Variance score: %.2f' % clf.score(X_test, y_test))
-----------------------------------------------------------------------
lasso 선형 회귀를 이용했고 cross validation 을 통해 모델을 평가했다.
물론 시계열 데이터로 회귀를 사용하는게 잘 맞는지는 모르겠지만,
선형 회귀를 공부하고 실습할 수 있는 좋은 계기가 되었다.
정확도는 매우 낮은 편이다. 
하지만 1주일간 예측 매출과 실제 매출을 비교해보면 오차범위는 15만원 이내이기 때문에
첫 예측 코드치고 충분히 만족할만한 결과를 도출했다.

댓글

이 블로그의 인기 게시물

윈도우 설치에서 파티션 설정 오류(NTFS)

[exploit writing] 1_스택 기반 오버플로우 (1) First

하둡 설치 오류 정리