PYTHON

구매 영수증 데이터 전처리 (평균방문주기)

한번해보즈아 2022. 9. 19. 18:15

아래의 데이터는 한 매장의 고객이 6월 한달동안 물품을 구매한 날짜를 기록해둔 데이터(ex.영수증)이며 간략한 설명을 붙이자면 1번 고객은 22년 6월 1일에 1번의 구매를 하였고, 2일에는 2번, 3일에도 구매를 한 경우이며 10번 고객은 22년 6월 23일 1번만 물품을 구매하였다. 

데이터 예시

영수증 데이터를 분석하다 보면 이러한 형식의 데이터를 주로 볼 수 있을것이며 이러한 형식으로 데이터가 있으면 단점이 주말에 몇번오고 평일엔 몇번 왔는지 파악하기가 어렵다는 점이다. 따라서 전처리를 적절하게 해줘야 하는데 이 페이지에서 다뤄보도록하겠습니다. 추가적으로 이 고객이 몇일 간격으로 방문하는지 평균 방문주기도 구해보도록 하겠습니다

 

import pandas as pd
from collections import Counter
from datetime import datetime
from tqdm import tqdm
from dateutil.parser import parse

# STORE_DATE_TOP1 날짜를 SET해서 리스트로 만드는 코드
df1 = df.copy()

aaa=[]

for idx, _ in tqdm(df1.iterrows(), total = df1.shape[0]):
    bbb =[i for i in list(set(df1['STORE_DATE_TOP1'][idx].split(',')))]
    bbb.sort()
    aaa.append(bbb)

 

 

위의 코드는 20220602, 20220602 이런식으로 중복된 날짜가 있는 데이터를 유니크한 값으로 변환해주며 ","로 구분되어있는 데이터를 정렬한다음 aaa라는 리스트에 append하는 코드입니다. 따라서 aaa에는 유니크한 날짜 데이터만 들어가 있습니다.

 

# SET한 날짜를 요일로 변경한 다음 요일별 카운트 하는 코드
majimak=[]
for i, _ in enumerate(tqdm(aaa)):
    ccc=[]
    for idx, _ in enumerate(aaa[i]):
        imsi=parse(aaa[i][idx]).strftime('%Y%m%d')
        imsi1 = datetime.strptime(imsi,'%Y%m%d')
        ccc.append('월화수목금토일'[imsi1.weekday()])
    majimak.append(ccc)
    
majimak

[['목',
  '금',
  '일',
  '월',
  '수',
  '금',
  '월',
  '화',
  '수',
  '금',
  '토',
  '월',
  '화',
  '수',
  '금',
  '토',
  '화',
  '수'],
 ['수', '목', '금', '일', '월', '목', '금', '일', '월', '화', '목', '금', '토'],
 ['목',
  '금',
  '일',
  '월',
  '수',
  '목',
  '토',
  '화',
  '수',
  '금',
  '토',
  '월',
  '목',
  '금',
  '토',
  '월',
  '화',
  '목'],

 

Date 데이터는 datetime 형식의 데이터 타입이 아니라 변형을 해주어야 하는데 strftime, strptime을 이용하여 datetime 형식의 데이터 타입으로 변형해준다음에  각각의 날짜가 무슨요일인지 표시해주는 코드입니다. 출력된 데이터는 1~3번째 고객의 방문요일을 나타낸것이며 예시로 1번고객이 목, 금, 일 이런식으로 방문을 하였다는것을 확인할수있습니다. 하지만 이렇게 보면 무슨요일에 몇번 방문했는지 확인이 어려우므로 또다른 전처리를 해줘야합니다

 

yoil = []
for idx, _ in enumerate(majimak):
    yoil.append(Counter(majimak[idx]))
    
yoil

[Counter({'목': 1, '금': 4, '일': 1, '월': 3, '수': 4, '화': 3, '토': 2}),
 Counter({'수': 1, '목': 3, '금': 3, '일': 2, '월': 2, '화': 1, '토': 1}),
 Counter({'목': 4, '금': 3, '일': 1, '월': 3, '수': 2, '토': 3, '화': 2}),

전처리를 통해 1~3번째 고객이 무슨요일에 몇번 왔는지 쉽게 파악할수 있습니다. 

 

이제 이 고객이 몇일에 한번씩 오는지 알 수 있는 "평균방문주기"를 구해보도록 하겠습니다

import numpy as np

joogi = []
for idx, _ in enumerate(tqdm(aaa)) :
    imsi=[]
    for i, _ in enumerate(aaa[idx]):
        try: 
            imsi.append(list(map(int,aaa[idx]))[i+1] - list(map(int,aaa[idx]))[i])

        except:
            pass
    joogi.append(imsi)
    
mean_cycle = []
for idx, _ in enumerate(tqdm(joogi)):
    if len(joogi[idx]) > 1 :
        mean_cycle.append(np.mean(joogi[idx]))
    else:
        mean_cycle.append(None)
        pass
    
df1['cycle']= mean_cycle
mean_cycle

Date 사이의 간격을 구하여 리스트에 입력한다음 numpy를 이용하여 각 고객마다 평균을 구하는 코드입니다.  

4번째 고객은 매일 방문하는것을 확인할수 있고 10번째고객은 3.5일마다 매장을 방문하는것을 확인할수있습니다.

2번째 for에서 if문의 의미는 1번 방문한 고객은 방문주기를 파악할 수 없으므로 None값을 입력하도록 처리했습니다.

 

 

그리고 마지막으로 요일별 카운트를 하긴했지만 매장운영에 있어서 평일, 주말구분이 중요한데 한달동안 평일에 몇번왔고 주말에 몇번왔는지 처리하는방법을 알아보도록 하겠습니다.

 # 평일,주말 카운트 해서 컬럼생성하는 코드

pyongil =['월', '화', '수', '목', '금']
pyongil_col = []
joomal_col = []
for idx, _ in enumerate(tqdm(joogi)):
    pyongil_cnt =0
    joomal_cnt=0
    for i, _ in enumerate(sorted(df1['yoil'][idx+1].elements())):
        if sorted(df1['yoil'][idx+1].elements())[i] in pyongil :
            pyongil_cnt += 1
        else:
            joomal_cnt += 1
    pyongil_col.append(pyongil_cnt)
    joomal_col.append(joomal_cnt)

df1['pyongil_col'] = pyongil_col
df1['joomal_col'] = joomal_col

df1


        pyongil_col joomal_col  
1                21          2  
2                18          0  
3                20          0  
4                22          8  
5                22          6  
...             ...        ...  
6           0          1  
7           0          1  
8           1          0  
9           0          1  
10         1          0

이러한 방법으로 한달동안 평일, 주말에 몇번씩 방문했는지 확인 할 수 있습니다.