📝

Chapter4. 데이터 전처리

 
 
 
 
 
크롤링을 통해 수집한 데이터를 데이터베이스에 적재하기 전에 데이터의 품질을 개선하고 분석에 용이한 형태로 데이터를 정제하고 가공하는 과정이 필요합니다. 이것을 데이터 전처리(Data Preprocessing) 과정이라고 합니다. 해당 챕터에서는 데이터 전처리에 활용되는 대표적인 라이브러리 2가지인 Pandas와 Numpy에 관해서 소개하고 예시와 함께 간단한 데이터 전처리 과정을 함께 살펴볼 것입니다.
 
 

4.1 데이터 전처리 라이브러리(Pandas, Numpy)

4.1.1 데이터 전처리(Data Preprocessing)

데이터 전처리(Data Preprocessing)는 다양한 형식으로 수집된 원시 데이터를 분석이나 모델링에 적합한 형태로 데이터를 정제하고 변환하는 과정으로, 데이터 마이닝 및 데이터 분석에서 매우 중요한 단계입니다. 이 단계에서 수행되는 작업은 데이터의 품질을 향상하고 모델의 성능을 향상하는데 결정적인 역할을 합니다.
 
여러 경로를 통해 수집된 데이터들은 정제되지 않아 오류, 결측치, 이상치 등의 문제점을 갖고 있습니다. 또한, 일관성 없는 형식과 구조를 가져 분석하기 쉽지 않을 수 있습니다. 이 때문에 데이터 전처리 단계에서 결측치를 적절한 값으로 대체하거나, 이상치를 제거하여 데이터의 왜곡을 줄임으로써 데이터의 품질을 개선할 수 있습니다. 또한, 데이터를 일관된 형식으로 변환하여 분석이나 모델링에 적합한 형태로 데이터를 재구성합니다.
 

4.1.2 Pandas

Pandas는 Python에서 데이터 조작 및 분석을 할 수 있는 강력한 라이브러리로, ‘관계형’ 혹은 ‘레이블이 된’ 데이터를 쉽게 다룰 수 있는 데이터 전처리 작업을 수행하기 위해 널리 사용되는 Python 패키지입니다. Pandas는 특히, 표 형태의 데이터를 다루는 데 용이하며, 데이터 정제 및 분석, 시각화 등에 특화되어 있습니다.
 

Pandas의 주요 기능 및 특징

Pandas의 주요 기능과 특징은 다음과 같습니다.
  • 데이터 로딩 및 저장 : 다양한 형태로 구성된 포맷( CSV, Excel, SQL, JSON 등)의 데이터를 불러오고 저장하는 기능을 제공합니다.
  • 데이터 조작과 처리 : 필요한 데이터만 선택하고 불필요한 데이터는 잘라내거나, 원하는 데이터들을 변형시키고 병합하는 등 다양한 조작 및 처리 작업을 수행할 수 있습니다.
  • 누락 데이터 처리: 데이터 분석에 부정적 영향을 끼칠 수 있는 데이터프레임 내의 결측치를 처리하고 해결할 수 있습니다.
  • 데이터 분석: 다양한 기능을 통해 통계적 분석, 집계, 피벗 테이블, 시계열 분석 등 다양한 데이터 분석 작업에 큰 도움을 줍니다.
  • 데이터 시각화 : Matplotlib과 함께 사용함으로써 분석하거나 불러온 데이터들을 그래프로 시각화할 수 있습니다. 이를 통해 시각적으로 한눈에 데이터의 패턴이나 추이를 파악할 수 있습니다.
 
이처럼 Pandas를 통해 다양한 포맷의 데이터들을 더욱 쉽게 가공할 수 있으며 유연하게 데이터를 처리할 수 있습니다. 또한 시각화하여 직관적으로 통찰력을 얻을 수 있습니다. Pandas는 러프한 데이터들을 불러와 데이터를 정제하고 분석하고 시각화하는 것까지 데이터 분석의 모든 과정에 도움을 주는 데이터 분석에 있어 필수적이고 강력한 라이브러리입니다.
 
Pandas 설치
그럼 Pandas 라이브러리를 설치해보겠습니다.
# Pandas 라이브러리 설치 !pip install pandas
 

Pandas의 기본 자료구조(Series, DataFrame)

Pandas는 Series, DataFrame, Panel 3가지의 자료 구조를 사용합니다. 그중 가장 많이 사용되는 Series와 DataFrame에 대해서 살펴보겠습니다.
 
Series
Series는 1차원 배열의 데이터를 다루는 데 사용되는데,각 데이터는 값(values)과 각 값에 해당하는 인덱스(index)를 동시에 갖게 됩니다.
import pandas as pd # Series 생성 series = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e']) # 결과 출력 series
➡️
결과
a 1 b 2 c 3 d 4 e 5 dtype: int64
 
다음과 같이 Series의 값과 인덱스를 각각 확인할 수 있습니다.
# Series 값 확인 print(series.values) # Series 인덱스 확인 series.index
➡️
결과
[1 2 3 4 5] Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
 
DataFrame
DataFrame은 2차원 데이터를 다루는 데 사용되며 2차원 데이터는 행과 열로 구성된 표 형태를 보이고 있습니다. DataFrame은 열(columns), 인덱스(index), 값(values)으로 구성됩니다.
import pandas as pd # 예제 데이터 생성 columns = ['col1', 'col2', 'col3'] index = ['index1', 'index2', 'index3'] values = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # DataFrame 생성 df = pd.DataFrame(values, index=index, columns=columns) # 결과 출력 df
➡️
결과
notion imagenotion image
 
DataFrame으로부터 열(columns), 인덱스(index), 값(values)을 각각 확인할 수 있습니다.
# DataFrame 칼럼 확인 df.columns
➡️
결과
Index(['col1', 'col2', 'col3'], dtype='object')
 
# DataFrame 인덱스 확인 df.index
➡️
결과
Index(['index1', 'index2', 'index3'], dtype='object')
 
# DataFrame 값 확인 df.values
➡️
결과
array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
 

4.1.3 Numpy

Numpy는 Python에서 여러 가지 연산 등을 효율적으로 도와줄 수 있는 다양한 기능을 제공합니다. 특히 과학 계산, 행렬이나 다차원 배열 연산, 수치 연산을 하는데 유용하게 사용되는 라이브러리입니다. 그렇기 때문에 어떤 데이터를 크롤링하여 더욱 정확하고 효율적으로 데이터 분석하는 데 큰 도움을 줄 수 있습니다.
 

Numpy의 주요 기능 및 특징

Numpy의 주요 기능과 특징은 다음과 같습니다.
  • 다차원 배열: Numpy가 가지고 있는 데이터 구조는 다차원 배열(ndarray)로 대표됩니다. 다차원 배열은 동일한 타입의 원소들로 구성된 다양한 차원의 데이터를 효율적으로 다루는 데 유용합니다. Numpy는 하나의 숫자값인 스칼라부터 1차원인 벡터, 2차원인 행렬, 3차원인 텐서까지 고차원의 데이터를 표현할 수 있습니다.
  • 빠른 연산: Numpy는 내장된 고유의 기능을 활용하여 비효율적인 코드들 없이도 가져온 데이터를 빠르게 연산할 수 있는 기능을 가졌습니다. 이러한 기능을 통해 수치 연산 작업 등을 손쉽게 해결할 수 있습니다.
  • 다양한 수학 함수: Numpy는 로그, 지수 통계함수, 삼각함수, 선형대수 함수 삼각함수 등 연산에 필요한 다양한 수학 함수를 제공합니다. 이를 통해 데이터를 분석 및 처리하고 통계적으로 활용하는 데 큰 도움을 받을 수 있습니다.
  • 데이터 입출력: Numpy는 손쉽게 배열을 디스크에 저장하고 로드할 수 있도록 도와줍니다. 이를 통해 다양한 배열로 이루어진 데이터를 빠르고 정확하게 저장하고 읽어 들일 수 있습니다. 또한 다른 파일 형식과의 데이터 변환도 자유롭게 수행할 수 있습니다.
 
이처럼 Numpy는 데이터를 분석하고 처리하는 데 필요한 다양한 기능을 가지고 있어 데이터 분석 부분에 있어서 필수적인 라이브러리라고 볼 수 있습니다. Numpy는 Pandas를 비롯해 과학 및 공학 연산에 유용한 SciPy, 그래프 등을 통해 데이터를 시각화할 수 있는 Matplotlib, 머신러닝 관련 라이브러리인 scikit-learn 등 다양한 패키지와 호환성도 좋아 데이터를 다루거나 정확한 연산 작업을 상대적으로 쉽고 효율적으로 수행하는 데도 큰 역할을 할 수 있습니다.
 
Numpy 설치
그럼 Numpy를 설치해보겠습니다.
# Numpy 라이브러리 설치 !pip install numpy
 

Numpy의 핵심 객체(ndarray)

Numpy의 핵심 객체는 다차원 배열인 ndarray(n-dimensional array)입니다. 이 ndarray 덕분에 Numpy는 배열 단위로 데이터를 관리하고 연산을 수행하므로 대용량의 데이터를 빠르게 처리할 수 있다는 장점이 있습니다. 또한, ndarray의 내부 데이터들은 모두 동일한 데이터 타입을 가지고 있다는 특징이 있습니다.
 
먼저 ndarray를 생성해 보도록 하겠습니다. ndarray를 생성하기 위해서는 np.array 함수에 리스트(list)와 같은 반복 가능한 객체를 인자로 넣어주면 됩니다. 다음과 같이 리스트를 인자로 넣어 1차원, 2차원, 3차원 배열을 각각 생성해 보도록 하겠습니다.
import numpy as np # 1차원 배열인 벡터 생성 a = np.array([1, 2, 3, 4, 5]) # 2차원 배열인 행렬 생성 b = np.array([[11, 12, 13], [14, 15, 16]]) # 3차원 배열인 텐서 생성 c = np.array([[[21, 22], [23, 24]], [[25, 26], [27, 28]]]) # 결과 출력 print('1차원 배열') print(a, '\n') print('2차원 배열') print(b, '\n') print('3차원 배열') print(c)
➡️
결과
1차원 배열 [1 2 3 4 5] 2차원 배열 [[11 12 13] [14 15 16]] 3차원 배열 [[[21 22] [23 24]] [[25 26] [27 28]]]
다음과 같이 각 배열의 타입을 확인해 보면 Numpy의 ndarray임을 확인할 수 있습니다.
print(type(a)) print(type(b)) print(type(c))
➡️
결과
<class 'numpy.ndarray'> <class 'numpy.ndarray'> <class 'numpy.ndarray'>
 
또한, 아래와 같은 함수들을 통해 배열의 차원이나 데이터 타입, 배열 내 각 요소가 소비한 바이트 수, 그리고 배열 내 요소가 소비한 총 바이트 수를 확인할 수 있습니다.
# 배열의 차원 확인 print(c.ndim) # 배열의 데이터 타입 확인 print(c.dtype) # 배열 내 각 요소가 소비한 바이트 수 확인 print(c.itemsize) # 배열 내 요소가 소비한 총 바이트 수 확인 print(c.nbytes)
➡️
결과
3 int32 4 32
 
 

4.2 데이터 정제 및 가공

4.2.1 데이터 타입 변환하기

데이터 타입은 변수나 값이 가지는 특성을 정의하며, 어떤 종류의 데이터가 어떤 유형인지 알려줍니다. 각 데이터의 타입들이 제각각이라면 호환성에 문제가 생길 수 있고 그렇게 되면 서로 간의 필요할 수 있는 간단한 연산조차 힘들어질 수 있습니다. 이뿐만 아니라 데이터 타입 변환은 데이터의 표현 및 저장과도 관련이 있습니다. 예를 들어, 날짜와 시간을 나타내는 문자열을 Datetime이라는 시간 객체로 변환하면 날짜 및 시간과 관련된 연산을 수행하기 용이하고 저장할 수 있습니다. 데이터 타입의 변환은 데이터를 다루는데 기본적인 개념이며 데이터를 적절히 다루고 처리할 때에 매우 중요합니다.
 

dtypes()

먼저, 아래와 같이 4X5의 데이터프레임을 생성하고, dtypes를 사용해 각 Column의 데이터 타입을 확인합니다.
import pandas as pd # 예시 데이터 생성 A = [1, 2, 3, 4, 5] B = [1.5, 2.5, 3.5, 4.5, 5.5] C = ['1', '2', '3', '4', '5'] D = [True, True, True, False, False] # DataFrame생성 df = pd.DataFrame(data={'A':A, 'B':B, 'C':C, 'D':D}) # 데이터 타입 확인 df.dtypes
➡️
결과
A int64 B float64 C object D bool dtype: object
 

astype()

특정 Column의 데이터 타입을 변경하고 싶다면, Dictionary 형식을 이용해 {’Column이름’: ‘변경하고자 하는 dtype’} 과 같이 입력해 줍니다.
# 데이터 타입 변경 df1 = df.astype({'C':'int64'}) # 데이터 타입 변경 확인 df1.dtypes
그럼, 다음과 같이 ‘C’ Column의 데이터 타입이 문자열에서 숫자, 즉 object에서 int64로 변경된 것을 확인할 수 있습니다. 다수의 Column을 변경하고 싶을 경우에도, 위와 같이 Dictionary 형식을 이용하면 됩니다.
➡️
결과
A int64 B float64 C int64 D bool dtype: object
 

4.2.2 데이터 결합하기

데이터 결합은 말 그대로 데이터를 하나로 합치는 것을 말합니다. 데이터 결합은 데이터를 효율적으로 다루고 원하는 결과를 도출하기 위해 중요한 작업입니다. 데이터 결합 역시 데이터 처리, 분석, 조작 등 다양한 작업에서 필수적 데이터를 정제하고 분석하는 데 있어 중요한 작업 중 하나이며, 데이터 처리, 분석, 조작 등 다양한 작업에서 필수적입니다. 데이터 결합은 원하는 부분에 따라 다양한 형태로 이루어질 수 있습니다. 문자열만 결합할 수도 있으며 배열 및 리스트의 결합, 데이터베이스 결합, 객체 간의 결합까지 다양하게 결합해 데이터를 활용할 수 있습니다.
 
Pandas에서는 다양한 방법으로 여러 개의 DataFrame을 결합하는 함수를 제공하고 있습니다. 대표적으로는 concat과 merge 함수가 존재합니다.
 

concat()

먼저, concat() 함수는 특정 축을 기준으로 DataFrame을 단순히 이어 붙여줍니다.
import pandas as pd # 첫번째 DataFrame 생성 df1 = pd.DataFrame({'a':[1, 2, 3, 4, 5], 'b':[6, 7, 8, 9, 10], 'c':[11, 12, 13, 14, 15]}) # 두번째 DataFrame 생성 df2 = pd.DataFrame({'a':[10, 20, 30, 40, 50], 'b':[60, 70, 80, 90, 100], 'c':[110, 120, 130, 140, 150], 'd':[160, 170, 180, 190, 200]}) # df1과 df2 DataFrame 결합 result = pd.concat([df1, df2]) # 결과 출력 result
➡️
결과
notion imagenotion image
 
위의 경우, df1과 df2를 위아래(행 방향)로 이어 붙여진 것을 확인할 수 있습니다. 각 DataFrame의 행 인덱스 번호가 그대로 유지되고, df1에는 d열이 없기 때문에 결측치로 채워진 것을 확인할 수 있습니다. 만약 행 인덱스 번호를 순서대로 다시 매기고 싶다면, ignore_index=True를 사용하면 됩니다.
# 새롭게 인덱스 번호를 매겨 df1과 df2 DataFrame 결합 result = pd.concat([df1, df2], ignore_index=True) # 결과 출력 result
➡️
결과
notion imagenotion image
 
DataFrame을 좌우(열 방향)로 이어 붙이고 싶다면, axis=1을 사용하면 됩니다.
# 열방향으로 df1과 df2 DataFrame 결합 result = pd.concat([df1, df2], axis=1, ignore_index=True) # 결과 출력 result
➡️
결과
notion imagenotion image
 

merge()

또한, 두 DataFrame에서 특정 key 값을 기준으로 병합할 수 있습니다.
import pandas as pd # 첫번째 예시 데이터 생성 data1 = {'col1' : ['용산구', '동작구', '서초구', '강남구'], 'col2' : [1, 2, 3, 4], 'col3' : ['a', 'b', 'c', 'd'], 'col4' : [1.5, 2.5, 3.5, 4.5]} # 두번째 예시 데이터 생성 data2 = {'col1' : ['동작구', '용산구', '강남구', '서초구'], 'col5' : ['aaa', 'bbb', 'ccc', 'ddd']} # 각각의 DataFrame 생성 df1 = pd.DataFrame(data1) df2 = pd.DataFrame(data2) # 두 데이터의 공통 Column 이름(col1)을 기준으로 df1과 df2 DataFrame 병합 result = pd.merge(df1, df2, on='col1') # 결과 출력 result
➡️
결과
notion imagenotion image
 

4.2.3 데이터 중복 처리하기

 

데이터 중복을 처리하는 이유

데이터의 중복은 많은 문제점을 야기할 수 있습니다. 데이터 중복은 데이터의 정확성에 심각한 타격을 줄 수 있습니다. 데이터를 분석하고 모델링하는 과정에서 데이터가 중복되어 들어있다면 중복이 없었을 경우 기대할 수 있었던 정확한 결과와 다른 결과를 초래할 수 있기 때문입니다. 또한, 분석의 효율성을 떨어뜨릴 수 있습니다. 중복데이터가 많아지면 분석에 드는 자원과 시간이 증가합니다. 그뿐만 아니라 중복 데이터를 제대로 제거하지 않으면 데이터와 저장 및 관리에 들어가는 저장 공간의 낭비를 야기해 큰 데이터의 경우 심각한 비효율성을 초래할 수 있습니다. 그러므로, 데이터가 중복되어 있다면 중복을 제거하여 정확성과 효율성을 향상시키고, 데이터의 분석 및 모델링의 신뢰도를 높이는 것이 바람직합니다.
 

Pandas로 중복 데이터 처리하기

import pandas as pd # 중복 데이터가 포함된 DataFrame 생성 data = { 'id': [1, 2, 3, 2, 2], 'name': ['John', 'Alice', 'Bob', 'Alice', 'Alice'], 'age': [25, 30, 35, 30, 30] } df = pd.DataFrame(data) # 중복 데이터 제거 df = df.drop_duplicates() # 결과 출력 df
다음과 같이 중복돼 있던 id : 2, name : Alice, age : 30이 해결된 결과를 확인할 수 있습니다.
➡️
결과
notion imagenotion image
 

Numpy로 중복 데이터 처리하기

import numpy as np # 중복 데이터가 포함된 배열 생성 arr = np.array([[1, 2, 3], [4, 5, 6], [1, 2, 3], [7, 8, 9]]) # 중복 행 제거 arr = np.unique(arr, axis=0) # 결과 출력 print(arr)
다음과 같이 1행과 중복된 값을 갖고 있는 3행이 없어진 것을 확인할 수 있습니다.
➡️
결과
[[1 2 3] [4 5 6] [7 8 9]]
 

4.2.4 결측치 처리하기

결측치는 데이터값의 부재를 뜻합니다. 데이터 세트에서 어떠한 변수 또는 항목에 대한 값이 빠졌거나 기록되지 않은 부분들이 결측치로 간주합니다. 결측치의 원인은 다양합니다. 예를 들어, 어떠한 조사에 있어 응답이 누락된 경우가 있을 수 있고, 데이터 수집 과정에서의 실수 및 오류로 인해 발생할 수 있습니다.
 
데이터의 결측치는 정확한 분석을 위해 주의해서 확인하고 정확하게 처리할 필요가 있습니다. 결측치가 있는 데이터를 처리하지 않고 사용하면 결측치가 없을 시 예상되는 결과와 다른 결과가 도출될 수 있기 때문입니다. 결측치는 직접 제거하거나 유효한 값으로 대체해 처리할 수 있는데, 처리하는 방법에 따라 분석의 정확성에 영향을 미칠 수 있기 때문에 결측치 처리는 데이터 분석 전처리의 중요한 단계라고 볼 수 있습니다.
 

결측치 확인하기 | isna(), isnull(), notna(), notnull()

DataFrame 내 결측치를 확인하는 방법에는 2가지가 있습니다.
 
첫 번째로는 isna()와 isnull()을 사용하여, 결측치일 경우엔 True를, 결측치가 아닐 경우엔 False를 반환합니다. 두 번째로는 notna()와 notnull()을 사용하여, 앞선 메서드와는 반대로 결측치일 경우엔 False를, 결측치가 아닐 경우엔 True를 반환합니다.
 
우선, 다양한 결측치가 포함된 3X5 DataFrame을 생성하도록 하겠습니다.
import pandas as pd import numpy as np # DataFrame 생성 columns=['A', 'B', 'C', 'D', 'E'] data = [[1, 2, 3, None, 5], ['가', '나', np.nan, '라', '마'], [pd.NA, 'b', 'c', 'd', 'e'] ] df = pd.DataFrame(data, columns=columns) # 결과 출력 df
➡️
결과
notion imagenotion image
 
isna(), isnull()
isnull()을 사용하여 결측치를 확인해 보도록 하겠습니다. 동일한 역할을 하는 함수로는 isna()가 있습니다.
 
아래 결과와 같이 결측값이었던 자리에는 True로, 결측값이 아닌 자리에는 False로 대체된 것을 확인할 수 있습니다.
# 결측치 확인 df.isnull()
➡️
결과
notion imagenotion image
 
notna(), notnull()
이번에는 notnull()을 사용하여 결측치를 확인해보도록 하겠습니다. 동일한 역할을 하는 함수로 notna()가 있습니다.
 
위 메서드와는 반대로 결측값이었던 자리에는 False로, 결측값이 아닌 자리에는 True로 대체된 것을 확인할 수 있습니다.
# 결측치가 아닌 값 확인 df.notnull()
➡️
결과
notion imagenotion image
 

결측치 제거하기 | dropna()

이렇게 확인한 결측치를 처리하기 위해서는 다양한 방법들이 존재합니다. 그중에서도 가장 간단하게 처리할 방법은 결측치를 제거하는 것입니다.
 
Pandas는 dropna()라는 함수를 제공하여, DataFrame으로부터 결측치를 제거합니다. 해당 함수가 사용될 경우에는 결측치가 하나라도 포함된 행을 모두 삭제합니다.
import pandas as pd import numpy as np # DataFrame 생성 columns = ['A', 'B', 'C', 'D', 'E'] data = [[1, 2, 3, 4, 5], ['가', '나', np.nan, '라', '마'], ['a', 'b', 'c', 'd', 'e'], [None, None, 13, 'apple', 'cider'] ] df = pd.DataFrame(data, columns=columns) # 결측치를 포함한 행 제거(사본 반환) df.dropna()
➡️
결과
notion imagenotion image
 
# 원본 DataFrame(변환 없음) print("원본 데이터프레임") df
➡️
결과
notion imagenotion image
 
반대로, 결측치가 하나라도 포함된 Column을 모두 삭제하는 경우도 있습니다. 이럴 때는 axis=1로 지정해주면 됩니다.
import pandas as pd import numpy as np # DataFrame 생성 columns = ['A', 'B', 'C', 'D', 'E'] data = [[1, 2, 3, 4, 5], ['가', '나', np.nan, '라', '마'], ['a', 'b', 'c', 'd', 'e'], [None, None, 13, 'apple', 'cider'] ] df = pd.DataFrame(data, columns=columns) # 결측치를 포함한 Column 제거 df.dropna(axis=1)
➡️
결과
notion imagenotion image
 
# 원본 데이터 확인 df
➡️
결과
notion imagenotion image
 
위의 경우에는 DataFrame의 원본은 변경되지 않은 채 사본을 반환하는 경우입니다. 만일 원본 DataFrame을 변경하고 싶다면 inplace=True로 설정하여 수정할 수 있습니다.
import pandas as pd import numpy as np # DataFrame 생성 columns=['A', 'B', 'C', 'D', 'E'] data = [[1, 2, 3, 4, 5], ['가', '나', np.nan, '라', '마'], ['a', 'b', 'c', 'd', 'e'], [None, None, 13, 'apple', 'cider'] ] df = pd.DataFrame(data, columns=columns) # 원본 데이터에 적용되어 변경 df.dropna(inplace=True) # 원본 데이터 확인 df
➡️
결과
notion imagenotion image
 

결측치 대체하기 | fillna()

앞서 결측값을 단순히 제거하는 것 외에 원하는 값으로 변경하고 싶다면 fillna()를 활용할 수 있습니다.
 
우선, 결측값을 일괄적으로 변경하고 싶다면, 다음과 같이 원하는 값을 괄호 안에 넣어주면 됩니다.
import pandas as pd import numpy as np # 예시 데이터 생성 columns=['A', 'B', 'C', 'D', 'E'] data = [[1, 2, 3, 4, 5], ['가', '나', np.nan, '라', '마'], ['a', 'b', 'c', 'd', 'e'], [None, None, 13, 'apple', 'cider'] ] # DataFrame 생성 df = pd.DataFrame(data, columns=columns) # 결과 출력 df.fillna('HI')
➡️
결과
notion imagenotion image
 
만일 각 Column값에 대해 원하는 값으로 변경하고 싶다면 Dictionary 형태로 입력하면 됩니다.
# 각 칼럼값을 key로, 변경하고자 하는 값을 value로 하는 딕셔너리 생성 dict = {'A': 'Hello', 'B': 'Hi', 'C': 100, 'D': 200, 'E': 300} # Dictionary를 통해 결측치 대체 df.fillna(dict)
다음과 같이 결측값이 대체된 것을 확인할 수 있습니다.
➡️
결과
notion imagenotion image
 

4.2.5 이상치 처리하기

이상치(Outliers)는 다른 데이터들의 값들과 확연하게 동떨어진값을 말합니다. 쉽게 말해 100점 만점인 시험 점수 데이터에 120점인 데이터가 있다거나, 대한민국의 8월 온도 데이터 중 어느 한 날의 온도가 영하 4도라면 이상치라고 판단할 수 있습니다. 이렇게 확연하게 눈에 띄는 이상치들 외에 이상치를 판단하는 기준은 데이터 수집의 목적과 데이터 고유의 특성에 따라 달라질 수 있지만 주로 IQR이라는 값을 기준으로 다음 같은 순서에 따라 판단합니다. 1) 사분위수 나누기 : 데이터 세트에 있는 데이터들을 최솟값부터 최댓값까지 순서대로 나열하고 4등분을 합니다. 이때 25% 값부터 중앙값까지의 값을 Q1, 중앙값을 Q2, Q2부터 75%까지의 값을 Q3라고 부르겠습니다. 2) IQR구하기 : IQR은 이상치를 판단하는데 기준을 잡아주는 값으로 Q3 - Q1으로 나타낼 수 있습니다. 3) 이상치의 기준 : 위에서 구한 IQR 값을 기준으로 이상치를 판단할 수 있습니다. Q1 - 1.5 * IQR 보다 작거나 Q3 + 1.5 * IQR 크면 일반적으로 이상치로 판단할 수 있습니다. 글로만 설명하면 이해가 어려울 수 있습니다. 다음은 IQR을 직관적으로 이해할 수 있는 이미지입니다.
 
이러한 이상치들은 데이터 분석을 하는 데 있어 정확성을 떨어뜨려 합리적인 의사결정에 부정적인 영향을 미칠 수 있습니다. 이상치를 처리하는 방법에는 대표적으로 이상치를 데이터에서 제거하는 방법과 이상치를 다른 값으로 대체하는 방법이 있습니다.
 

이상치 제거하기

이상치 제거는 이상치를 처리하는 가장 간단한 방법으로 데이터 세트에서 직접 이상치를 제거하는 방법입니다. 이상치의 제거는 이상치가 명확하고 이상치가 상대적으로 적을 때 유용합니다.
import pandas as pd # 예시 데이터 생성 data = pd.Series([1, 2, 3, 4, 100]) # IQR 계산 Q1 = data.quantile(0.25) # 1사분위수 Q3 = data.quantile(0.75) # 3사분위수 IQR = Q3 - Q1 # 이상치 제거 data = data[(data >= Q1 - 1.5 * IQR) & (data <= Q3 + 1.5 * IQR)] # 결과 출력 data
다음과 같이 눈으로 쉽게 확인할 수 있었던 이상치 100이 해결된 것을 확인할 수 있습니다.
➡️
결과
0 1 1 2 2 3 3 4 dtype: int64
 
그러나 이상치를 오판해 유의미한 정보를 제거하지 않도록 주의할 필요가 있습니다. 정상적인 값들을 이상치로 판단해 제거하거나 대체한다면 왜곡된 결과를 얻게 되고, 데이터 분석에 큰 악영향을 줄 수 있기 때문입니다.
 

이상치 대체하기

이상치의 대체는 이상치를 다른 값으로 대체하는 방법입니다. 이상치를 대체할 때는 주변의 다른 값들의 통계적 속성이나 데이터의 흐름을 고려하여 대체해야 합니다. 대체 가능한 값들은 데이터마다 다를 수 있지만 주로 평균, 중앙값, 주변 데이터 값을 활용할 수 있습니다.
import pandas as pd import numpy as np # 예시 데이터 생성 data = pd.Series([1, 2, 3, 4, 100]) # IQR 계산 Q1 = data.quantile(0.25) # 1사분위수 Q3 = data.quantile(0.75) # 3사분위수 IQR = Q3 - Q1 # 이상치 대체를 위한 상하한값 계산 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR # 이상치 대체 data[(data < lower_bound) | (data > upper_bound)] = data.median() # 결과 출력 data
다음과 같이 눈으로도 쉽게 확인할 수 있었던 이상치 값인 100이 중앙값(median) 3으로 대체된 것을 알 수 있습니다. 이 예시에서는 중앙값을 사용했지만, 데이터에 따라 타당한 데이터로 대체할 수 있습니다.
➡️
결과
0 1 1 2 2 3 3 4 4 3 dtype: int64
 

4.2.6 정규표현식을 사용한 URL 제거

URL을 제거하는 것은 텍스트 데이터의 정제와 분석 목적에 따른 전처리 과정 중 하나입니다. 어떤 데이터를 크롤링할 때 그 데이터가 정확한 수치 같은 정량적인 데이터일 수도 있지만 일반적인 텍스트 형태일 수도 있습니다. '정규표현식을 사용한 URL 제거'는 텍스트에 포함돼 있을 수 있는 불필요한 URL을 제거함으로써 텍스트의 일관성을 유지하고 가독성을 올리는 데 유용합니다. 또한 상대적으로 길고 지저분한 URL을 제거하여 데이터 저장 및 처리에 필요한 자원을 절약하는 데 도움을 줄 수 있습니다.
 
정규표현식을 통해 다음과 같이 URL이 제거된 상태로 결과가 출력되는 것을 알 수 있습니다.
import re # 정규표현식을 불러오는 모듈 def remove_urls(text): pattern = re.compile(r'https?://\S+|www\.\S+') return re.sub(pattern, '', text) # url이 들어있는 텍스트 text = "이 문장은 www.example.com과 https://www.test.com 같은 URL을 포함합니다." clean_text = remove_urls(text) # 결과출력 clean_text
➡️
결과
'이 문장은 같은 URL을 포함합니다.’