내일배움캠프(QA,QC_5기)

[내일배움캠프] QA/QC_5기 ( 56일차 )

lshxkwh 2026. 5. 28. 20:28

EV 주행 데이터 전처리 파이프라인

전기차 주행 로

1  컬럼명 오탈자 수정 

 

원본 데이터에 Velocity [km/h]]]처럼 대괄호가 중복된 컬럼이 존재하더라. 해당 컬럼의 값을 올바른 컬럼으로 병합한 뒤 제거 

df_cleaned = df.copy()

df_cleaned['Velocity [km/h]'] = (
    df_cleaned['Velocity [km/h]']
    .fillna(df_cleaned['Velocity [km/h]]]'])
)

df_cleaned = df_cleaned.drop(columns=['Velocity [km/h]]]'])

df_cleaned['Velocity [km/h]'].isnull().sum()


Velocity [km/h]  결측치 0개 확인

 

2 불필요 컬럼 제거
상관계수 0.9 이상인 중복 계열 컬럼과 결측치가 과다한 컬럼을 제거. HVAC 세부 송풍구, 냉각수 온도 계열, 히터 전력 계열 등이해당
import numpy as np
corr = df_cleaned.corr(numeric_only=True)

high_corr = (
    corr.where(~np.eye(corr.shape[0], dtype=bool))
        .unstack()
        .dropna()
)

high_corr = high_corr[
    abs(high_corr) > 0.9
].sort_values(key=abs, ascending=False)

print(high_corr)

#Battery Temperature [℃], SoC [%], Ambient Temperature [℃],
drop_cols = [
    'Unnamed: 23',

    # SoC 중복 계열
    'displayed SoC [%]',
    'min. SoC [%]',
    'max. SoC [%)',

    # 배터리 온도 중복
    'max. Battery Temperature [℃]',

    # 히터/전력 중복 계열
    'Heating Power LIN [W]',
    'Heater Current [A]',
    'Requested Heating Power [W]',
    'Heater Signal',

    # 외기온 중복
    'Ambient Temperature Sensor [℃]',

    # 냉각수/열교환기 중복 계열
    'Coolant Temperature Heatercore [℃]',
    'Coolant Temperature Inlet [℃]',
    'Temperature Coolant Heater Inlet [℃]',
    'Temperature Coolant Heater Outlet [℃]',
    'Temperature Heat Exchanger Outlet [℃]',

    # HVAC 세부 송풍구 센서
    'Temperature Defrost lateral left [℃]',
    'Temperature Defrost lateral right [℃]',
    'Temperature Defrost central [℃]',
    'Temperature Defrost central left [℃]',
    'Temperature Defrost central right [℃]',

    'Temperature Footweel Driver [℃]',
    'Temperature Footweel Co-Driver [℃]',

    'Temperature Feetvent Co-Driver [℃]',
    'Temperature Feetvent Driver [℃]',

    'Temperature Head Co-Driver [℃]',
    'Temperature Head Driver [℃]',

    'Temperature Vent right [℃] ',
    'Temperature Vent central right [℃]',
    'Temperature Vent central left [℃]',

    # Heating Power CAN [kW]와 중복되는 데이터
    'Heater Voltage [V]',
    # 절반 이상이 결측치, TripB 전용 공통모델 안정성 떨어짐
    'Coolant Volume Flow +500 [l/h]'
]

df_refined = df_cleaned.drop(columns=drop_cols, errors='ignore')

 

제거 카테고리

SoC 중복 계열 , 배터리 온도 중복, 히터 전력 중복, 외기온 중복 ,냉각수 온도 중복 , HVAC 송풍구 센서 , 고결측 컬럼

 

3 Trip_ID 및 시간 기준 정렬
 

Trip_ID를 첫 번째 컬럼으로 이동하고, Trip 내에서 시간 순서가 보장되도록 정렬

# TripID 앞으로
df_1 = ['Trip_ID'] + [col for col in df_refined.columns if col != 'Trip_ID']
df_refined = df_refined[df_1]
# 순서 정렬
df_refined = df_refined.sort_values(['Trip_ID','Time [s]']).reset_index(drop=True)
df_refined.head(10)

 

4 결측치 보간
 

Trip 단위로 그룹화하여 선형 보간 → bfill → ffill 순서로 결측치를 채웁니다. 보간이 불가능한 컬럼은 삭제.

#결측치 보간
interp_cols = {
    'SoC [%]',
    'Requested Coolant Temperature [℃]'
}

for col in interp_cols:
  df_refined[col] = (
      df_refined.groupby('Trip_ID')[col].
      transform(lambda x: x.interpolate().bfill().ffill())
  )

df_refined[['SoC [%]', 'Requested Coolant Temperature [℃]']].isnull().sum()

# Requested Coolant Temperature [℃] Trip 단위 통째로 비어있어서 보간 불가 -> 삭제
df_refined = df_refined.drop(columns=['Requested Coolant Temperature [℃]'])

df_refined.isnull().sum()

 

5 1초 단위 리샘플링

원본 데이터는 0.1초 간격이다. astype(int)로 1초 구간에 묶어 Trip_ID별 평균을 집계.

  • 0.0 ~ 0.9초 → 0초 구간으로 통합
  • 1.0 ~ 1.9초 → 1초 구간으로 통합
  • 각 구간 내 수치는 평균값으로 집계
# astype(int)를 통해서 0~0.9는 0초 1~1.9초는 1초 이런식으로 묶음
df_refined['Time_bin'] = df_refined['Time [s]'].astype(int)

# 기존 0.1초 Time 컬럼 제거
df_refined = df_refined.drop(columns=['Time [s]'])

# Trip_ID별로 나누고 1초 구간별 평균값 만들기
df_resampled = (df_refined.groupby(['Trip_ID','Time_bin']).mean(numeric_only=True).reset_index())

# 컬럼명을 다시 Time [s]로 변경해줌
df_resampled = df_resampled.rename(columns = {'Time_bin' : 'Time [s]'})

df_resampled.head()
 


0.1초 → 1초 간격으로 데이터 크기 약 10배 축소