본문 바로가기
데이터 분석/혼자 공부하는 데이터 분석 with 파이썬

[혼공분석] 3주차_데이터 정제하기

by yEvery 2025. 1. 20.

03-1 불필요한 데이터 삭제하기

 

데이터 정제: 데이터에서 손상되거나 부정확한 부분을 수정하고, 불필요한 데이터를 삭제하거나 불완전한 값을 교체하는 등의 작업, 데이터를 분석 목적에 맞게 변환하는 데이터 랭글링 또는 데이터 먼징의 일부로 수행될 수 있음

 

열 삭제하기

ns_book = ns_df.loc[:, '번호':'등록일자']

selected_columns = ns_df.columns != 'Unnamed: 13'
ns_book = ns_df.loc[:, selected_columns]

ns_book = ns_df.drop('Unnamed: 13', axis=1)
ns_book.drop('주제분류번호', axis=1, inplace=True)

ns_book = ns_df.dropna(axis=1)
ns_book = ns_df.dropna(axis=1, how='all')
  1. loc 메서드에 슬라이싱 사용
  2. 불리언 배열 사용: 판다스 배열 성격의 객체는 어떤 값과 비교할 때 자동으로 배열에 있는 모든 원소와 하나씩 비교하는 원소별 비교를 진행한다.
  3. drop() 메서드: 첫 번째 매개변수에 삭제하려는 열 이름, axis 매개변수를 1로 지정, inplace 매개변수를 True로 지정하면 현재 선택한 데이터프레임을 바로 수정할 수 있다.
  4. dropna() 메서드: NaN이 하나 이상 포함된 행이나 열을 삭제, how 매개변수를 all로 지정하면 모든 값이 NaN인 열을 삭제할 수 있다.

행 삭제하기

ns_book2 = ns_book.drop([0,1])

ns_book2 = ns_book[2:]
ns_book2 = ns_book[0:2]

selected_rows = ns_df['출판사'] == '한빛미디어'
ns_book2 = ns_book[selected_rows]
  1. drop() 메서드: axis 매개변수를 0으로 지정, 기본값이므로 생략해도 가능
  2. []연산자와 슬라이싱: [] 연산자에 슬라이싱을 사용하면 마지막 인덱스를 포함하지 않음
  3. []연산자와 불리언 배열: 가장 즐겨 사용하는 방접, 조건을 [] 연산자에 바로 사용하는 경우가 많다
  4. loc 메서드, dropna() 메서드도 사용 가능
sum(ns_book.duplicated())
sum(ns_book.duplicated(subset=['도서명', '저자', 'ISBN']))
dup_rows = ns_book.duplicated(subset=['도서명', '저자', 'ISBN'], keep=False)

duplicated() 메서드: 데이터프레임에 있는 모든 열을 기준으로 중복된 행을 찾는다. 일부 열을 기준으로 중복된 행을 찾으려면 subset 매개변수에 기준 열을 나열, keep 매개변수를 False로 지정하면 중복된 모든 행을 True로 표시

duplicates() 메서드: 중복된 행을 삭제

group_df = count_df.groupby(by=['도서명', '저자', 'ISBN', '권'], dropna=False)

groupby() 메서드: by 매개변수에 행을 합칠 때 기준이 되는 열을 지정,

                             지정된 열에 NaN이 포함되어 있으면 해당 행을 삭제

                       →  dropna 매개변수를 False로 지정하면 NaN이 있는 행도 포함

unique_rows = ~dup_rows
ns_book3 = ns_book[unique_rows].copy()

~연산자: 결과를 반전시킬 때 사용

copy() 메서드: 데이터프레임의 복사본을 만듦. 판다스는 copy() 메서드를 사용하지 않으면 데이터프레임을 별도의 메모리 공간에 저장되는지 보장하지 X, 일부 행이나 열을 선택하여 데이터를 업데이트할 때는 항상 복사하는 것이 좋다.

ns_book3.set_index(['도서명', '저자', 'ISBN', '권'], inplace=True)

ns_book3.update(loan_count)

ns_book4 = ns_book3.reset_index()

set_index() 메서드: 지정한 열을 인덱스로 설정

update() 메서드: 다른데이터프레임을 사용해 원본 데이터프레임의 값을 업데이트

 reset_index() 메서드: 데이터프레임 인덱스를 재설정


기본 숙제(필수): p. 182의 확인 문제 2번 풀고 인증하기

4번은 col3열의 합을 계산한다.


03-2 잘못된 데이터 수정하기

 

판다스는 누락된 값을 기본적으로 NaN으로 표시

ns_book4.info()
ns_book4.info(memory_usage='deep')

info() 메서드: 열마다 NaN이 아닌 값이 몇 개나 있는지 확인할 수 있다. memory_usage 매개변수'deep' 옵션을 지정하면 정확한 메모리 사용량을 얻을 수 있다.

ns_book4.isna().sum()

isna() 메서드: NaN을 직접 카운트, 각 행이 비어 있는지를 나타내는 불리언 배열을 반환, sum() 메서드를 이어서 호출 시 불리언 배열의 True 개수로 비어 있는 행 개수를 얻을 수 있다. 

ns_book4.loc[0, '도서권수'] = None
ns_book4.loc[0, '부가기호'] = np.nan

ns_book4 = ns_book4.astype({'도서권수': 'int32', '대출건수': 'int32'})

누락된 값으로 표시하기

  • 판다스 데이터프레임에서 정수를 저장하는 열에 파이썬의 None을 입력
  • 넘파이 패키지에 있는 np.nan을 사용

astype() 메서드: 데이터 타입을 지정할 때, 매개변수를 딕셔너리 형식으로 전달

set_isbn_na_rows = ns_book4['세트 ISBN'].isna()
ns_book4.loc[set_isbn_na_rows, '세트 ISBN'] = ''

ns_book4.fillna('없음').isna().sum()
ns_book4['부가기호'].fillna('없음').isna().sum()
ns_book4.fillna({'부가기호': '없음'}).isna().sum()

replace(원래 값, 새로운 값) #바꾸려는 값이 하나일 때
replace([원래 값1, 원래 값2], [새로운 값1, 새로운 값2]) #바꾸려는 값이 여러 개
replace({원래 값1: 새로운 값1, 원래 값2: 새로운 값2}) # 딕셔너리 형식
replace({열 이름: 원래 값}, 새로운 값) #열 마다 다른 값으로 바꿀 때

누락된 값을 바꾸기

  • loc 메서드: 누락된 값을 가리키는 불리언 배열을 만든 후 loc 메서드에 전달
  • fillna() 메서드: 바꾸길 원하는 값을 전달, 특정 열을 선택한 후 fillna() 메서드를 적용하면 열 이름 없이 개수만 있는 판다스 시리즈 객체로 반환, 전체 데이터프레임을 반환하려면 열 이름과 바꾸려는 값으로 이루어진 딕셔너리를 전달
  • replace() 메서드: NaN 뿐만 아니라 어떤 값도 바꿀 수 있음
ns_book4.replace({'발행년도': {r'\d\d(\d\d)': r'\1'}}, regex=True)
# \d\d\d\d = \d{4}

정규 표현식(정규식): 문자열 패턴을 찾아서 대체하기 위한 규칙의 모음

  • 그룹으로 묶을 때: 괄호 사용, 그룹을 나타낼 때는 \1, \2처럼 사용(순서대로)
  • regex=True: 정규 표현식을 사용한다는 의미
  • r 문자: 정규 표현식을 다른 문자열과 구분하기 위해 접두사처럼 사용
  • 중괄호: 반복될 때, 중괄호 안에 숫자를 사용하여 개수를 지정
  • \d: 숫자
ns_book4.replace({'저자': {r'(.*)\s\(지은이\)(.*)\s\(옮긴이\)': r'\1\2'},
                  '발행년도': {r'\d{2}(\d{2})': r'\1'}}, regex=True)

문자 찾기

  • .(마침표): 어떤 문자에도 대응
  • \s: 공백 문자
  • *: 0개 이상 반복
  • \: 일반 문자라고 인식
ns_book4['발행년도'].str.contains('1988').sum()
invalid_number = ns_book4['발행년도'].str.contains('\D', na=True)
ns_book5['발행년도'].gt(4000).sum()

contains() 메서드: 시리즈나 인덱스에서 문자열 패턴을 포함하고 있는지 검사,

                               누락된 값이 있다면 기본적으로 np.nan으로 채움

                          → na 매개변수True로 지정하면 누락된 행True로 표시

gt() 메서드: 전달된 값보다 큰 값을 찾음

\D: 숫자가 아닌 다른 모든 문자


이전 장에서의 웹 스크래핑에서 requests 패키지를 사용한 것과 이번 장에서 데이터를 정제하는 것 둘 다를 이용하여 누락된 정보를 채웠다.

join() 메서드: 추출한 결과를 하나의 문자열로 합쳐준다.

오류가 발생하더라도 함수 실행이 종료되지 않고 계속 추출하도록 try~except문으로 예외 처리

apply() 메서드는 기본적으로 반한된 값을 튜플로 만들기 때문에 result_type 매개변수expand로 지정해서 각기 다른 열로 만들도록 한다.


추가 숙제(선택): p. 219의 확인 문제 5번 풀고 인증하기