2018년 12월 24일 월요일

구매 내역과 특징 feature 추출 with pandas

0. 서론

구매 내역에서 특징 feature를 추출하기 위한 작업에 대해 고민해보았습니다. 아래 표는 순수한(raw)상태의 data 입니다. date는 예를 들기위한 데이터로 현시점 기준 이전 개월수로 이해하면 좀 더 편합니다.
위 데이터를 이름별로 나타내보았습니다. 그 중에 Micle이라는 사람만 정리해 보면 아래와 같습니다. PA, PB라는 상품이 다르기 때문에 구별을 따로 해야하고 판매한 개월수도 다릅니다.
이것을 제대로 구현을 한다면 다음과 같이 구현이 됩니다.
PA라는 제품을 언제 구매했는지 컬럼으로 나타내는것입니다. 이렇게 표시하게되면 많은 차원이 소모됩니다.

그래서 가중치를 주는 방법인데요. 균등하게 하느냐 비균등하게 하느냐인데 여기에서는 개월수가 작을수록 좁은 가중치를 사용하는 방법을 사용하여 나타내어 보았습니다.
3/6/12/24 이런식으로 표현하였습니다. 3에는 0~3까지 표시, 6의 경우 4~6까지, 12은 7~12까지를 포함하는 수치로 표현하도록 하였습니다. 이렇게 되면 아래와 같은 형태로 많은 차원을 줄일 수 있습니다. 만약 숫자가 큰 부분이 중요하다고 판단되면 반대로 표현하여야 합니다.
이것을 Python 으로 구현하도록 하겠습니다.

1. Data 준비

data.csv
Name,Product,Date,Sell count
Micle,PA,5,1
Sally,PA,2,3
Pop,PC,6,4
Micle,PB,7,3
Pop,PA,6,2
Sally,PB,2,3
Micle,PA,9,4
Pop,PB,10,5
Sally,PA,13,6
Sally,PB,2,2
Pop,PC,7,3
Micle,PA,15,1

2. 구현 소스

구현방법은 원하는 부분만 select 하여 sum을 구해 새로운 dataframe을 만든는 방식입니다.
import pandas as pd

df = pd.read_csv("data.csv", delimiter=',', header=0)
print("## All")
print(df)
 
print("## Name")
df_name = df["Name"].drop_duplicates()
print(df_name)
print("## Product")
df_product = df["Product"].drop_duplicates()
print(df_product)

PRIOD_COND=[(0,3),(4,6),(7,12),(13,24),(25,48),(49,96),(97,999)]

df_o = pd.DataFrame({})

for name in list(df_name):
 tlist = [name]
 for product in list(df_product):
  for condl,condh in PRIOD_COND:
   df_c = df.copy()
   df_c = df_c.loc[(df_c['Name'] == name)&(df_c['Product'] == product)&(df_c['Date'] >= condl)&(df_c['Date'] <= condh)]
   print("## select ",name,product,condl,condh)
   if(len(df_c.index)>0):
    print(df_c)
    print("sum",df_c["Sell count"].sum())
   tlist.append(df_c["Sell count"].sum())
 print(tlist)
 df_o = df_o.append( pd.DataFrame(tlist).T )
print ("## Result1")
print (df_o)

tlist = ["Name"]
for product in list(df_product):
 for condl,condh in PRIOD_COND:
  tlist.append(product+"_"+str(condh))
  
df_o.columns=(tlist)
print ("## Result2")
print (df_o)

3. 결과

## All
     Name Product  Date  Sell count
0   Micle      PA     5           1
1   Sally      PA     2           3
2     Pop      PC     6           4
3   Micle      PB     7           3
4     Pop      PA     6           2
5   Sally      PB     2           3
6   Micle      PA     9           4
7     Pop      PB    10           5
8   Sally      PA    13           6
9   Sally      PB     2           2
10    Pop      PC     7           3
11  Micle      PA    15           1
## Name
0    Micle
1    Sally
2      Pop
Name: Name, dtype: object
## Product
0    PA
2    PC
3    PB
Name: Product, dtype: object
## select  Micle PA 0 3
## select  Micle PA 4 6
    Name Product  Date  Sell count
0  Micle      PA     5           1
sum 1
## select  Micle PA 7 12
    Name Product  Date  Sell count
6  Micle      PA     9           4
sum 4
## select  Micle PA 13 24
     Name Product  Date  Sell count
11  Micle      PA    15           1
sum 1
## select  Micle PA 25 48
## select  Micle PA 49 96
## select  Micle PA 97 999
## select  Micle PC 0 3
## select  Micle PC 4 6
## select  Micle PC 7 12
## select  Micle PC 13 24
## select  Micle PC 25 48
## select  Micle PC 49 96
## select  Micle PC 97 999
## select  Micle PB 0 3
## select  Micle PB 4 6
## select  Micle PB 7 12
    Name Product  Date  Sell count
3  Micle      PB     7           3
sum 3
## select  Micle PB 13 24
## select  Micle PB 25 48
## select  Micle PB 49 96
## select  Micle PB 97 999
['Micle', 0, 1, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0]
## select  Sally PA 0 3
    Name Product  Date  Sell count
1  Sally      PA     2           3
sum 3
## select  Sally PA 4 6
## select  Sally PA 7 12
## select  Sally PA 13 24
    Name Product  Date  Sell count
8  Sally      PA    13           6
sum 6
## select  Sally PA 25 48
## select  Sally PA 49 96
## select  Sally PA 97 999
## select  Sally PC 0 3
## select  Sally PC 4 6
## select  Sally PC 7 12
## select  Sally PC 13 24
## select  Sally PC 25 48
## select  Sally PC 49 96
## select  Sally PC 97 999
## select  Sally PB 0 3
    Name Product  Date  Sell count
5  Sally      PB     2           3
9  Sally      PB     2           2
sum 5
## select  Sally PB 4 6
## select  Sally PB 7 12
## select  Sally PB 13 24
## select  Sally PB 25 48
## select  Sally PB 49 96
## select  Sally PB 97 999
['Sally', 3, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0]
## select  Pop PA 0 3
## select  Pop PA 4 6
  Name Product  Date  Sell count
4  Pop      PA     6           2
sum 2
## select  Pop PA 7 12
## select  Pop PA 13 24
## select  Pop PA 25 48
## select  Pop PA 49 96
## select  Pop PA 97 999
## select  Pop PC 0 3
## select  Pop PC 4 6
  Name Product  Date  Sell count
2  Pop      PC     6           4
sum 4
## select  Pop PC 7 12
   Name Product  Date  Sell count
10  Pop      PC     7           3
sum 3
## select  Pop PC 13 24
## select  Pop PC 25 48
## select  Pop PC 49 96
## select  Pop PC 97 999
## select  Pop PB 0 3
## select  Pop PB 4 6
## select  Pop PB 7 12
  Name Product  Date  Sell count
7  Pop      PB    10           5
sum 5
## select  Pop PB 13 24
## select  Pop PB 25 48
## select  Pop PB 49 96
## select  Pop PB 97 999
['Pop', 0, 2, 0, 0, 0, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0]
## Result1
      0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21
0  Micle  0  1  4  1  0  0  0  0  0  0  0  0  0  0  0  0  3  0  0  0  0
0  Sally  3  0  0  6  0  0  0  0  0  0  0  0  0  0  5  0  0  0  0  0  0
0    Pop  0  2  0  0  0  0  0  0  4  3  0  0  0  0  0  0  5  0  0  0  0
## Result2
    Name PA_3 PA_6 PA_12 PA_24 PA_48 PA_96 PA_999 PC_3  ...   PC_96 PC_999 PB_3 PB_6 PB_12 PB_24 PB_48 PB_96 PB_999
0  Micle    0    1     4     1     0     0      0    0  ...       0      0    0    0     3     0     0     0      0
0  Sally    3    0     0     6     0     0      0    0  ...       0      0    5    0     0     0     0     0      0
0    Pop    0    2     0     0     0     0      0    0  ...       0      0    0    0     5     0     0     0      0

[3 rows x 22 columns]

4. 소스 분석

df = pd.read_csv("data.csv", delimiter=',', header=0)
CSV파일을 읽어서 dataFrame 형태를 만듭니다.

print("## Name")
df_name = df["Name"].drop_duplicates()
print(df_name)
print("## Product")
df_product = df["Product"].drop_duplicates()
print(df_product)
위 코드는 Name과 Product의 중복 되는 이름을 제거합니다.

PRIOD_COND=[(0,3),(4,6),(7,12),(13,24),(25,48),(49,96),(97,999)]
date를 범위를 위한 미리 범위 table을 준비합니다.

df_c = df.copy()
df_c = df_c.loc[(df_c['Name'] == name)&(df_c['Product'] == product)&(df_c['Date'] >= condl)&(df_c['Date'] <= condh)]
df_c에 df를 복사하여 처리를 합니다. colmum값 조건에 맞는 row 데이터를 선택하고자 할때 위와 같이 표현합니다. loc는 row를 선택할때 사용합니다. 그리고 각각의 조건은 & 로 연결됩니다.

   print("## select ",name,product,condl,condh)
   if(len(df_c.index)>0):
    print(df_c)
    print("sum",df_c["Sell count"].sum())
조건에 맞으면 위 코드에서 출력이 일어납니다. 그리고 얻은 dataframe에서 sum()을 구해서 출력하면 다음과 같은 결과가 나옵니다.
## select  Sally PB 0 3
    Name Product  Date  Sell count
5  Sally      PB     2           3
9  Sally      PB     2           2
sum 5

   tlist.append(df_c["Sell count"].sum())
 print(tlist)
 df_o = df_o.append( pd.DataFrame(tlist).T )
print ("## Result1")
print (df_o)
list인 tlist에 sum값을 추가하고 이것을 다시 DataFrame에 추가를 합니다. 이때 column, row를 교환하는것이 T 입니다. 해당결과가 Result1으로 나타납니다.
## Result1
      0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21
0  Micle  0  1  4  1  0  0  0  0  0  0  0  0  0  0  0  0  3  0  0  0  0
0  Sally  3  0  0  6  0  0  0  0  0  0  0  0  0  0  5  0  0  0  0  0  0
0    Pop  0  2  0  0  0  0  0  0  4  3  0  0  0  0  0  0  5  0  0  0  0

위 결과에 column label 만 넣으면 됩니다. 해당 과정을 하는 코드가 다음 코드입니다.
tlist = ["Name"]
for product in list(df_product):
 for condl,condh in PRIOD_COND:
  tlist.append(product+"_"+str(condh))
  
df_o.columns=(tlist)
이름의 리스트를 만들어서 columns 에 넣어주면 변경됩니다.




댓글 없음:

댓글 쓰기