반응형

결측치 다루기
- 결측치는 영어로 missing value라고 합니다. 값이 없는 것이죠. null이라고 표현하기도 하고 NA, NAN이라고 하기도 합니다.
- 데이터 만들기
import pandas as pd
import numpy as np
np.random.seed(0) # 무작위로 숫자 추출하는데 첫 결과 고정. 실험조건을 동일하게 맞춰주기 위함
data = np.random.randint(0, 10, size=(10, 3)).astype(float)
data

- 결측치 만들기 - 값이 3이하인 것은 nan 처리 하겠습니다.
data[data < 3] = np.nan
data

- data를 데이터프레임으로 바꾸겠습니다. 이때 컬럼명은 col1, col2, col3로 설정하겠습니다.
- 그리고 습관적으로 .info()를 확인합니다. 새로운 데이터가 생겼다면 정보를 간단하게 확인할 수 있는 코드입니다.
df = pd.DataFrame(data, columns=["col1", "col2", "col3"])
df.info()

- 이렇게도 null을 확인할 수 있습니다.
df.isna().sum()

- col2와 col3에 결측치가 존재합니다.
- 결측치를 처리하는 방법은 여러 가지가 있습니다. 그 중에서 오늘은 평균으로 대치하는 방법을 쓰겠습니다.
- 나중에 결측치를 처리하는 여러 가지 방법에 대해 포스팅을 하겠습니다.
- 두 가지 방법을 소개해드립니다.
# 첫 번째 방법
df = df.fillna(df.mean())
df
# 조금 더 명시적인게 좋다고 함
# inplace는 지양한다고 함(파이썬에서)
col3_mean = df['col3'].mean()
# col3_mean
df['col3']= df['col3'].fillna(col3_mean)
df['col2']= df['col2'].fillna(df['col2'].mean())
df

결측치, 이상치 데이터 핸들링
데이터 불러오기
- 우선 다음처럼 library를 import 합니다.
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import statsmodels
import scipy
import seaborn as sns
print(pd.__version__)
print(np.__version__)
print(matplotlib.__version__)
print(statsmodels.__version__)
print(scipy.__version__)
print(sns.__version__)
- 데이터를 가지고 옵니다.
DATA_PATH = './'
covidtotals = pd.read_csv(DATA_PATH + "data/covidtotalswithmissings.csv")
covidtotals.head(5)
- pandas에서 보는 옵션을 다음과 같이 설정합니다.
pd.set_option('display.width', 40)
pd.set_option('display.max_columns', 20)
pd.set_option('display.max_rows', 20)
pd.options.display.float_format = '{:,.2f}'.format
- covidtotals의 인덱스를 iso_code 열로 설정하겠습니다.
covidtotals = covidtotals.set_index('iso_code')
covidtotals.head()

결측치 처리하기
- 인구 통계 컬럼에서 결측치 데이터를 확인합니다.
- 컬럼 방향으로 결측치의 갯수를 파악합니다.
- 다섯가지 인구 통계 변수 중에서 3개가 누락된 곳, 4개가 누락된 곳을 확인합니다.
totvars = ['location','total_cases','total_deaths','total_cases_pm','total_deaths_pm'] # 코비드 확진자 관련 변수
demovars = ['population','pop_density','median_age','gdp_per_capita', 'hosp_beds'] # 인구 통계 관련 변수
covidtotals[demovars].isnull().sum(axis=0)

- 위의 코드는 컬럼 별 결측치의 수를 알아보는 것입니다.(axis=0)
- 각 행 별 결측치 수는 다음과 같이(axis=1) 할 수 있고, .value_counts()를 사용하면 요약 형태로 볼 수 있습니다.
demovars_misscnt = covidtotals[demovars].isnull().sum(axis=1)
# demovars_misscnt
demovars_misscnt.value_counts()


결측치가 3개 이상인 데이터 추출하기
# covidtotals.loc[:, ['location'] + demovars].head(1)
# covidtotals.loc[demovars_misscnt >= 3, ['location'] + demovars].head()
covidtotals.loc[demovars_misscnt >= 3, ['location'] + demovars].T # 행/열 뒤집기

Index Alignment
- 인덱스 값끼리 연산이 이뤄지는 것입니다. Pandas에서 제공합니다.
- 다음 코드와 같이 인덱스 순서가 달라도, 같은 인덱스끼리 값이 합쳐지는 것을 볼 수 있습니다. 결과는 >>> 아랫줄에 썼습니다.
s1 = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
s2 = pd.Series([4, 3, 2, 1], index=['d', 'c', 'b', 'a'])
# print(s1, "\n", s2)
print(s1 + s2)
>>>
a 2
b 4
c 6
d 8
dtype: int64
- s1 + s2를 하면 순서대로 5, 5, 5, 5가 나올 것 같지만 a끼리, b끼리 더해져서 2, 4, 6, 8의 결괏값을 가집니다.
코로나 관련 변수만 추출하기
- totvars를 사용하여 결측값이 있는 국가를 찾아봅시다.
# 방법 1
demovars_misscnt = covidtotals[covidtotals[totvars].isna().any(axis=1)]
demovars_misscnt
# 방법 2
covidtotals[totvars].isnull().sum(axis=0)
totvarsmisscnt = covidtotals[totvars].isnull().sum(axis=1)
covidtotals.loc[totvarsmisscnt>0].T


데이터의 구간 나누기 (qcut)
- total_cases와 total_deaths가 숫자로 나와있는데 이걸 인식하기 쉽게 다섯 개의 구간을 나누어 매우낮음~매우높음으로 설정하겠습니다.
- qcut은 빈도수에 따라 구간을 나누는 것입니다. (cut은 구간 길이에 따라 나눕니다.)
- q 값 만큼 구간을 등분합니다.
covidtotalsonly = covidtotals.loc[:, totvars]
# covidtotalsonly
covidtotalsonly['total_cases_q'] = pd.qcut(covidtotalsonly['total_cases'],
labels = ['매우 낮음', '낮음', '중간', '높음', '매우 높음'],
q=5, precision=0)
covidtotalsonly['total_deaths_q'] = pd.qcut(covidtotalsonly['total_deaths'],
labels = ['매우 낮음', '낮음', '중간', '높음', '매우 높음'],
q=5, precision=0)
covidtotalsonly.head(2)

- 두 컬럼을 시각화해보겠습니다.
pd.crosstab(covidtotalsonly['total_cases_q'], covidtotalsonly['total_deaths_q'])

- 여기서 이상치는 무엇일까요? 우리가 눈여겨봐야 하는 건 그 이상치입니다. 여기에 해당하는 국가를 코드로 구현해서 찾을 것입니다.

- 주황색으로 표시한 부분은 당연한 결과입니다. 아무래도 케이스가 많을수록 사망자 수도 많을 것입니다. 이러한 경향성에서 멀수록 우리는 해석할 이유가 있다는 것입니다.
- 예를 들어 total_cases가 '낮음'이고 total_deaths가 '높음'인 한 국가가 어느 나라인지 다음의 코드로 찾을 수 있습니다.
covidtotals.loc[(covidtotalsonly.total_cases_q == '낮음') & (covidtotalsonly.total_deaths_q == '높음')].T

행 추가하기
- 다음 데이터프레임을 입력합니다.
df = pd.DataFrame({
"이름": ["Evan", "Sara", "Chris", "Messi", "Woods", "Jordan"],
"국어": [70, 90, None, None, 100, 85],
"영어": [65, 100, None, 90, 70, 80]
})
df

- 인덱스 6에 해당하는 행을 추가하겠습니다.
df.loc[6, "이름":"영어"] = ["kim", 50, 60]
df

- 국어 점수가 90점 이상이면 A, 80점 이상이면 B, C 나머지는 F인 열을 추가하는 것은 어떻게 할까요?
# 방법 1
df['등급'] = df['국어'].apply(lambda score: 'A' if score >= 90 else ('B' if score >= 80 else ('C' if score >= 70 else 'F')))
df
# 방법 2
# pandas & numpy
# numpy에 where 조건식이 있음. 한번만 적용하면 됨. - 참일 때, 거짓일 때
# 다중 조건식일 때는?
# np.where(조건식, 참, np.where(조건식, 참))
# np.select(다중조건식, 다중결괏값, default ==> else 조건)
condition_list = [(df["국어"] >= 90), (df['국어'] >= 80) & (df['국어'] < 90), (df['국어'] >= 70) & (df['국어'] < 80)]
choice_list = ["A", "B", "C"]
df['점수'] = np.select(condition_list, choice_list, default = "F")
df

감사합니다.
'Python > Pandas, Matplotlib, Seaborn' 카테고리의 다른 글
| [Visualization]_데이터 변환-그래프로 확인하기 (0) | 2023.08.30 |
|---|---|
| [Pandas]_Pandas library basic (4) 날짜 데이터 / shift (0) | 2023.08.09 |
| [Pandas]_Pandas library basic (2) loc & iloc 의 차이는? (0) | 2023.08.09 |
| [Pandas]_Pandas library basic (1) I/O, 행과 열 추출 (0) | 2023.08.09 |