λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Projects/πŸͺ Convenience Store Location Analysis

[Mini Project] 8. Feature Engineering (μ΄μƒμΉ˜μ™€ 뢄포 탐색)

by ISLA! 2023. 9. 13.

 

πŸ₯‘ 였늘의 λͺ©ν‘œ_Featrue Engineering

  • μ΅œμ’…λ°μ΄ν„°μ˜ μ£Όμš” μ»¬λŸΌμ„ 면적으둜 λ‚˜λˆ„μ–΄μ„œ, 면적당 n의 수의 κ°œλ…μœΌλ‘œ μŠ€μΌ€μΌλ§ μ‹œλ„
  • 전체 μ»¬λŸΌμ„ 3개 파트둜 λ‚˜λˆ„μ–΄μ„œ 각자 피쳐 μ—”μ§€λ‹ˆμ–΄λ§μ„ κ°„λ‹¨νžˆ μ‹œλ„ν•΄λ³΄κΈ°λ‘œ ν–ˆλ‹€.
  • λ˜ν•œ, μƒκΆŒμ„ 골λͺ©μƒκΆŒκ³Ό 비골λͺ©μƒκΆŒ(λ°œλ‹¬μƒκΆŒ λ“±)으둜 λ‚˜λˆ„μ–΄ 뢄석을 μ§„ν–‰ν•˜κΈ°λ‘œ ν–ˆλ‹€.
  • λ‚˜λŠ” μ•„νŒŒνŠΈ λ‹¨μ§€μˆ˜μ™€ μ„ΈλŒ€μˆ˜, 배후지 μ•„νŒŒνŠΈ λ‹¨μ§€μˆ˜μ™€ μ„ΈλŒ€μˆ˜λ₯Ό λ‹΄λ‹Ήν–ˆλ‹€.
  • μ•„νŒŒνŠΈ κ΄€λ ¨ μ»¬λŸΌμ€ λ‹€μŒκ³Ό κ°™μœΌλ©°, 배후지 λ°μ΄ν„°λŠ” 골λͺ©μƒκΆŒμ—λ§Œ μ‘΄μž¬ν•œλ‹€.
cols_gol = ['μ•„νŒŒνŠΈ_단지_수', 'μ•„νŒŒνŠΈ_가격_1_μ–΅_미만_μ„ΈλŒ€_수',
       'μ•„νŒŒνŠΈ_가격_1_μ–΅_μ„ΈλŒ€_수', 'μ•„νŒŒνŠΈ_가격_2_μ–΅_μ„ΈλŒ€_수', 'μ•„νŒŒνŠΈ_가격_3_μ–΅_μ„ΈλŒ€_수',
       'μ•„νŒŒνŠΈ_가격_4_μ–΅_μ„ΈλŒ€_수', 'μ•„νŒŒνŠΈ_가격_5_μ–΅_μ„ΈλŒ€_수', 'μ•„νŒŒνŠΈ_가격_6_μ–΅_이상_μ„ΈλŒ€_수', '배후지_μ•„νŒŒνŠΈ_단지_수',
       '배후지_μ•„νŒŒνŠΈ_가격_1_μ–΅_미만_μ„ΈλŒ€_수', '배후지_μ•„νŒŒνŠΈ_가격_1_μ–΅_μ„ΈλŒ€_수', '배후지_μ•„νŒŒνŠΈ_가격_2_μ–΅_μ„ΈλŒ€_수',
       '배후지_μ•„νŒŒνŠΈ_가격_3_μ–΅_μ„ΈλŒ€_수', '배후지_μ•„νŒŒνŠΈ_가격_4_μ–΅_μ„ΈλŒ€_수', '배후지_μ•„νŒŒνŠΈ_가격_5_μ–΅_μ„ΈλŒ€_수',
       '배후지_μ•„νŒŒνŠΈ_가격_6_μ–΅_이상_μ„ΈλŒ€_수']

 

 

πŸ₯‘ μ΄μƒμΉ˜ 탐색

πŸ‘‰  골λͺ©μƒκΆŒμ˜ μ•„νŒŒνŠΈ/μ„ΈλŒ€ 수 뢄포 μ‹œκ°ν™” (λ°•μŠ€ν”Œλ‘―)

nrows = 4
ncols = 4
fig, axes = plt.subplots(nrows = nrows, ncols = ncols, figsize = (20, 10))

for i, col in enumerate(cols_gol):
    row_idx = i // ncols
    col_idx = i % ncols
    axes[row_idx, col_idx].boxplot(df_gol[col])
    axes[row_idx, col_idx].set_title(f'{col} Box Plot')
    axes[row_idx, col_idx].set_ylabel('Value(κ°’)')
    
plt.tight_layout()
plt.show()

 

πŸ‘‰  비골λͺ©μƒκΆŒμ˜ μ•„νŒŒνŠΈ/μ„ΈλŒ€ 수 뢄포 μ‹œκ°ν™” (λ°•μŠ€ν”Œλ‘―)

 


 

πŸ₯‘ 뢄포 νŒŒμ•…

πŸ‘‰  골λͺ©μƒκΆŒμ˜ μ•„νŒŒνŠΈ/μ„ΈλŒ€ 수 뢄포 (νžˆμŠ€ν† κ·Έλž¨)

nrows = 2
ncols = 4
fig, axes = plt.subplots(nrows = nrows, ncols = ncols, figsize = (20,10))

for i, col in enumerate(cols_etc):
    row_idx = i // ncols
    col_idx = i % ncols
    axes[row_idx, col_idx].boxplot(df_etc[col])
    axes[row_idx, col_idx].set_title(f'{col} Box Plot')
    axes[row_idx, col_idx].set_ylabel('Value(κ°’)')
    
plt.tight_layout()
plt.show()

 

πŸ‘‰  비골λͺ©μƒκΆŒμ˜ μ•„νŒŒνŠΈ/μ„ΈλŒ€ 수 뢄포 (νžˆμŠ€ν† κ·Έλž¨)

μ½”λ“œλŠ” μœ„μ™€ 동일


πŸ₯‘  μ΄μƒμΉ˜ μΆ”κ°€ 탐색(IQR 이용)

πŸ‘‰  골λͺ©μƒκΆŒ 데이터셋 ν”Όμ²˜μ˜ μ΄μƒμΉ˜ κ°œμˆ˜μ™€ λΉ„μœ¨

  • 비골λͺ©μƒκΆŒλ„ λ™μΌν•˜κ²Œ 진행
  • ν”Όμ²˜λ³„ μ΄μƒμΉ˜ λΉ„μœ¨μ΄ 5% 내외이며, λ°˜λ“œμ‹œ μ œκ±°ν•  이유λ₯Ό 찾지 λͺ»ν•΄ 이상값 μ œκ±°λŠ” μ•ˆν•˜κΈ°λ‘œ 함
def outlier_iqr(data, column): 

    # lower, upper κΈ€λ‘œλ²Œ λ³€μˆ˜ μ„ μ–Έν•˜κΈ°     
    global lower, upper    
    
    # 4λΆ„μœ„μˆ˜ κΈ°μ€€ μ§€μ •ν•˜κΈ°     
    q25, q75 = np.quantile(data[column], 0.25), np.quantile(data[column], 0.75)          
    
    # IQR κ³„μ‚°ν•˜κΈ°     
    iqr = q75 - q25    
    
    # outlier cutoff κ³„μ‚°ν•˜κΈ°     
    cut_off = iqr * 1.5          
    
    # lower와 upper bound κ°’ κ΅¬ν•˜κΈ°     
    lower, upper = q25 - cut_off, q75 + cut_off     
    
    # print('IQR은',iqr, '이닀.')     
    # print('lower bound 값은', lower, '이닀.')     
    # print('upper bound 값은', upper, '이닀.')    
    
    # 1사 λΆ„μœ„μ™€ 4사 λΆ„μœ„μ— μ†ν•΄μžˆλŠ” 데이터 각각 μ €μž₯ν•˜κΈ°     
    data1 = data[data[column] > upper]     
    data2 = data[data[column] < lower]   
    
    num_outliers = data1.shape[0] + data2.shape[0]
    
    # μ΄μƒμΉ˜ 총 개수 κ΅¬ν•˜κΈ°
    return num_outliers
for i in cols_gol:
    print(f'col:{i}')
    result = outlier_iqr(df_gol, i)
    result_ratio = round(result/df_gol[i].shape[0] * 100, 2)
    print(f'μ΄μƒμΉ˜ 개수: {result}')
    print(f'μ΄μƒμΉ˜ λΉ„μœ¨: {result_ratio}%')
    print('\n')

 

 

 

πŸ₯‘  κ°„λ‹¨ν•œ 상관관계 뢄석

πŸ‘‰  골λͺ©μƒκΆŒ 데이터셋 ν”Όμ²˜μ˜ 상관관계 μ‹œκ°ν™”(히트맡)

correlation_matrix = df_gol.corr()
mask = np.triu(np.ones_like(correlation_matrix, dtype=bool))
mask |= correlation_matrix < 0.4

plt.figure(figsize=(10, 6))  
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1, mask = mask, annot_kws={"size": 8})
plt.title('상관 κ³„μˆ˜ 히트맡')
plt.show()


🀾 Issue Today

  • 톡합 데이터 ν”„λ ˆμž„μ—μ„œμ˜ 결츑치 문제
  • μ»¬λŸΌλ³„ λ°•μŠ€ν”Œλ‘― μ‹œκ°ν™” κ³Όμ •μ—μ„œ 골λͺ©μƒκΆŒμ—λ§Œ μ‘΄μž¬ν•˜λŠ” 배후지 μ•„νŒŒνŠΈ 데이터에 κ²°μΈ‘μΉ˜κ°€ μ‘΄μž¬ν•˜μ˜€μŒμ„ λ’€λŠ¦κ²Œ 확인
  • ν•΄λ‹Ή λ°μ΄ν„°λŠ” νŠΉμ • μƒκΆŒμ˜ 배후지(반경 200m라고 함)의 μ•„νŒŒνŠΈ κ°€κ²©λŒ€λ³„ μ„ΈλŒ€μˆ˜λ₯Ό μˆ˜μ§‘ν•œ 것
    πŸ‘‰ 직접 데이터λ₯Ό μΆ”κ°€ν•˜κ±°λ‚˜ μ œκ³΅λ°›μ€ RawDataμ—μ„œ κ²°μΈ‘μΉ˜κ°€ μ‘΄μž¬ν•œ κ²ƒμ΄μ—ˆμŒ
    πŸ‘‰ 결츑치λ₯Ό “λŒ€μ²΄”ν•˜λŠ” κ²ƒμœΌλ‘œ 의결
  • λŒ€μ²΄ 데이터 μ„ μ •μ—μ„œλŠ” μ»¬λŸΌλ³„ mean VS median 으둜 이견이 μžˆμ—ˆμœΌλ‚˜, 뢄포(νžˆμŠ€ν† κ·Έλž¨μ€ 그렀짐)λ₯Ό 확인해본 κ²°κ³Ό μ΄μƒμΉ˜ λΉ„μœ¨μ΄ 높지 μ•Šμ•„μ„œ, mean으둜 결츑치λ₯Ό 채움
for col in cols_bae:
    col_mean = df_gol[col].mean()
    df_gol[col].fillna(col_mean, inplace = True)

 


🀾 To Do List

  • νŒŒμƒλ³€μˆ˜ 생성 및 평가
  • 둜그 λ³€ν™˜ κ³ λ €(뢄포에 λ”°λ₯Έ μ •κ·œν™”)
  • ν”Όμ²˜ λ“œλž μ—¬λΆ€ νŒλ‹¨
  • λͺ¨λΈλ§ μ½”λ“œ ν™•μ •(κ°•μ‚¬λ‹˜κ»˜ ν”Όλ“œλ°± λ°›κΈ°)
728x90