부트캠프 정리

[멋쟁이사자처럼 데이터분석 부트캠프 5주차]-데이터전처리기초

지니248 2025. 7. 31. 19:56
이번 주차에는 Pandas를 활용한 데이터 전처리 기초에 대해 학습했습니다.
데이터 불러오기부터 결측치 처리, 자료형 변환, 시계열 처리, 이상치 탐지까지,
전처리 과정에서 자주 사용하는 함수들을 실습을 통해 익혔습니다.
⚠️본 글은 부트캠프 수업 내용을 기반으로 한 개인 학습 기록입니다.

✅ 데이터 전처리 기초

1. 데이터 불러오기

df = pd.read_csv('파일경로명.csv')

⚠️ 주의할 점 : 처음 불러온 원본 데이터를 df에 저장했다면, 전처리 시 덮어쓰기보다 복사본 사용 권장

df = pd.read_csv('데이터이름.csv')       # 원본  
df_copy = df.copy()                    # 복사본 사용

 

2. 전처리 필수 작업

📌 공백 제거

  🔹strip()

df['name'] = df['name'].str.strip()

📌 중복 제거

  🔹 drop_duplicates()

df = df.drop_duplicates()

📌 결측치 확인

  🔹 isnull().sum()

df.isnull().sum()
  • isnull() : 결측치인 경우 True, 아닌 경우 False를 반환
  • sum() : True는 1, False는 0으로 계산되므로, 각 열(column)별로 결측치 개수를 반환

 

📌 결측치 채우기

  🔹 fillna()

#평균값으로 채우기
df['age'] = df['age'].fillna(df['age'].mean())

#최빈값으로 채우기
df['성별'] = df['성별'].fillna(df['성별'].mode()[0])

#특정값으로 채우기
df.fillna('코스타리카', inplace=True)
  • fillna() : 결측치를 원하는 값으로 채우는 함수
  • inplace=True : 원본 데이터프레임(df)을 직접 수정

📌 결측치 삭제

  🔹dropna()

  • 결측치를 포함할지 여부를 선택하는 옵션
df_drop = df.dropna()
  • dropna = True : NaN값을 제외하고 계산 (기본값)
  • dropna = False : NaN도 포함해서 계산

📌 고유값 관련

  🔹nunique() / unique()

df['컬럼'].nunique()  # 고유값 개수(숫자)
df['컬럼'].unique()   # 고유값 목록(배열)

📌 자료형 변환

  🔹astype()

df['가격'] = df['가격'].astype(int)
  • 불리언 ➡️ 정수 변환
    • True → 1
    • False → 0
  • 문자열 ➡️ 정수 변환
    • '3'(문자열 숫자) →  3 (문자열이 숫자일 경우 가능)
    • 'a' → ❌ 에러 발생 (숫자가 아닌 문자는 변환 불가)

📌 행/열 삭제

  🔹drop()

#행 삭제
df.drop(1, axis=0, inplace=True)

#컬럼 삭제
df.drop('칼로리', axis=1, inplace=True)

📌 데이터 정렬

  🔹sort_index() / sort_values()

df.sort_index(ascending=False)  
df.sort_values('메뉴', ascending=False)
  • sort_index() : 행(또는 열)의 인덱스 값 기준으로 정렬
  • sort_values() : 열의 실제 데이터 값 기준으로 정렬

📌 조건 필터링

  🔹조건식 + 연산자

df[(df['f3'] == 'gold') & (df['f2'] == 2)]

📌 문자열 변경

  🔹replace()

df['메뉴'].replace({'아메리카노': '룽고', '녹차': '그린티'}, inplace=True)

📌 시계열 처리

  🔹pd.to_datetime()

df['DateTime1'] = pd.to_datetime(df['DateTime1'], format='%y-%m-%d %H:%M:%S')
#df['DateTime2'] = pd.to_datetime(df['DateTime2'] ) #2024-02-18 14-55-45 형태를 인식을 못한 포멧을 알려줘야한다
df['DateTime2'] = pd.to_datetime(df['DateTime2'] , format = '%Y-%m-%d %H-%M-%S') #월:m, 분:M
  • 날짜 형태를 pd.to_datetime()이 인식할 수 있도록 format을 맞춰주어야 함
  • format = '%y/%m/%d' → y, m, d, h, M, s 등의 포맷 약어를 사용
  • ⚠️ 날짜 형식과 실제 데이터의 구분자('-', '/', ':' 등)를 정확히 맞춰야 오류 없이 인식됨

 

🔹dt.dayofweek / dt.to_period()

df['날짜'].dt.dayofweek       # 요일 (0: 월요일 ~ 6: 일요일)  
df['날짜'].dt.to_period('Q')  # 분기 추출

 

  • Datetime 데이터 ➡️ Period(기간) 객체로 변환
  • 연도, 분기, 월, 일, 시 등 기간 단위로 데이터를 다루고 싶을 때 사용
  • .dt.to_period('Y'): 연도만 추출 ➡️ 2025
  • .dt.to_period('Q'): 분기 추출 ➡️ 2025Q1, 2025Q4
  • .dt.to_period('M'): 연-월 추출 ➡️ 2025-07
  • .dt.to_period('D'): 연-월-일 추출 ➡️ 2025-07-25
  • .dt.to_period('H'): 연-월-일-시 추출 ➡️ 2025-07-25 13:00

📌 값 세기

  🔹value_counts()

df['컬럼'].value_counts()

 

🔹idxmax()

df['컬럼'].value_counts().idxmax()
  • value_counts() : 각 값이 몇 번 나왔는지 세어줌 (빈도수)
  • idxmax() : 가장 큰 값을 가진 인덱스 반환 ➡️ 'value_counts().idmax()'로 최빈값 구할 수 있음

📌 이상치 탐지

  🔹quantile() / IQR()

  • IQR (Interquartile Range) : 데이터의 중간 50% 범위를 나타냄 ➡️이상치 탐지 기준으로 사용
  • 사분위수
    • Q1(1분위) : 하위 25% 지점
    • Q2(2분위) : 중앙값 (하위 50%) 
    • Q3(3분위) : 하위 75% 지점
    • IQR : Q3 - Q1 (중간 50% 범위)
#1단계. 분위수 및 IQR 계산
q3 = df['views'].quantile(0.75)  # Q3: 상위 25% 경계
q1 = df['views'].quantile(0.25)  # Q1: 하위 25% 경계
IQR = q3 - q1                    # IQR: 사분위 범위

#2단계. 이상치 기준 구하기
line1 = q1 - (1.5 * IQR)
line2 = q3 + (1.5 * IQR)

#3단계. 이상치 추출
con1 = df['views'] < line1
con2 = df['views'] > line2

df_outliers = df[con1 | con2]

#다른 방식. 바로 조건 필터링
detection = df[(df['views'] < (q1 - 1.5 * IQR)) | (df['views'] > (q3 + 1.5 * IQR))]

📌 포함 여부 확인

  🔹isin()

df['컬럼'].isin(['값1', '값2'])
  • 시리즈의 각 값이 리스트에 포함되어 있는지 여부를 True/False로 반환

📌 조건절

  🔹where()

df['컬럼'].where(df['컬럼'] > 10)
  • 조건을 만족하지 않으면 NaN 처리

📌 병합

  🔹concat() / merge()

#concat()
pd.concat([df1, df2], axis=0, ignore_index = True)


#merge()
pd.merge(df1, df2, on='ID', how='left')  # inner, left, right, outer
  • ⚠️ concat 주의 사항
    • 두 데이터의 행 개수가 같아야 함
    • 인덱스가 일치하지 않으면 NaN값 발생
      • ignore_index = True
      • 인덱스를 무시하고 0부터 다시 부여 (기본값은 ignore_index = False)
      • axis = 0 즉, 행 방향으로 붙일 때만 인덱스를 새로 부여

📌 이동 통계

  🔹rolling()

  • 이동창(window)을 적용해서 연속된 값들의 통계량을 구하는 함수
# sales 컬럼의 3일 이동 평균
# 최근 3일차의 평균을 계속 계산해주는 방식

df['sales_rolling'] = df['sales'].rolling(window=3).mean()

# window=3은 앞의 3개를 묶어서 계산하겠다는 의미

 

  • 슬라이딩 윈도우를 움직이면서 통계량을 구함
  • 시계열 데이터나 센서 데이터 분석에서 자주 사용
  • window : 이동 창의 크기 (몇 개씩 묶을지 지정)
  • .mean() : 이동 평균
  • .sum() : 이동 합계
  • .std() : 이동 표준편차
  • .max() / .min() : 이동 최대값/최소값

📌 요약 통계

  🔹describe()

  • 데이터프레임의 기초 통계 요약 제공
df.describe()

📊 제공되는 정보 (숫자형 데이터 기준)

  • count : 값의 개수
  • mean : 평균
  • std : 표준편차
  • min : 최솟값
  • 25%/50%/75% : 분위수 (사분위수)
  • max : 최댓값

✔️ 요약 정리

 

[기본 전처리]

  • 공백 제거: str.strip()
  • 중복 제거: drop_duplicates()
  • 결측치 확인: isnull().sum()
  • 결측치 채우기: fillna()
  • 결측치 삭제: dropna()

[데이터 정보 확인 및 변환]

  • 고유값 개수 확인: nunique(), 고유값 목록: unique()
  • 자료형 변환: astype()
  • 날짜형 변환: pd.to_datetime()
  • 날짜 정보 추출: .dt.dayofweek, .dt.to_period()

[데이터 정제 및 필터링]

  • 행 삭제: drop(인덱스, axis=0)
  • 열 삭제: drop(컬럼명, axis=1)
  • 조건 필터링: 조건식 + &, |
  • 문자열 변경: replace()
  • 특정 값 포함 여부 확인: isin()
  • 조건 만족하지 않으면 NaN 처리: where()

[데이터 분석용]

  • 값 세기: value_counts()
  • 최빈값 추출: idxmax()
  • 이상치 탐지: quantile(), IQR
  • 이동 통계 계산: rolling() + .mean(), .sum(), .std()

[데이터 병합]

  • 데이터 병합: concat(), merge()

[기초 통계 확인]

  • 통계 요약 확인 : describe()