파이썬
데이터프레임_정리
초롱씨
2023. 12. 5. 17:04
728x90
반응형
데이터프레임 행단위/열단위 합치기¶
In [1]:
import pandas as pd
<행단위 합치기>
In [3]:
### 임시 데이터 생성
# 임시 데이터
data = [["Dog",3],["Cat",5],["Tiger",2]]
index = [0,1,2]
columns = ["동물","나이"]
df_temp1 = pd.DataFrame(data, index=index, columns=columns)
df_temp1
Out[3]:
동물 | 나이 | |
---|---|---|
0 | Dog | 3 |
1 | Cat | 5 |
2 | Tiger | 2 |
In [4]:
### 임시 데이터 생성
# 임시 데이터
data = [["집",0],["초원",0],["초원",1]]
index = [0,1,2]
columns = ["사는곳","뿔의갯수"]
df_temp2 = pd.DataFrame(data, index=index, columns=columns)
df_temp2
Out[4]:
사는곳 | 뿔의갯수 | |
---|---|---|
0 | 집 | 0 |
1 | 초원 | 0 |
2 | 초원 | 1 |
행단위로 합치기¶
In [13]:
adf= pd.concat([df_temp1,df_temp2] ,axis=0, ignore_index=True)
adf
Out[13]:
동물 | 나이 | 사는곳 | 뿔의갯수 | |
---|---|---|---|---|
0 | Dog | 3.0 | NaN | NaN |
1 | Cat | 5.0 | NaN | NaN |
2 | Tiger | 2.0 | NaN | NaN |
3 | NaN | NaN | 집 | 0.0 |
4 | NaN | NaN | 초원 | 0.0 |
5 | NaN | NaN | 초원 | 1.0 |
열단위로 합치기¶
In [17]:
adf= pd.concat([df_temp1,df_temp2] ,axis=1, ignore_index=False)
adf
Out[17]:
동물 | 나이 | 사는곳 | 뿔의갯수 | |
---|---|---|---|---|
0 | Dog | 3 | 집 | 0 |
1 | Cat | 5 | 초원 | 0 |
2 | Tiger | 2 | 초원 | 1 |
<열단위 합치기 : 키값을 이용해서 합치는 방식>¶
In [24]:
### 임시 데이터 생성
data1 = {"국적코드":[1001,1002,1003],
"국가":["한국","미국","인도"]}
df_info1 = pd.DataFrame(data1)
data2 = {"국적코드":[1001,1001,1005],
"인구":[100, 200, 300]}
df_info2 = pd.DataFrame(data2)
df_info1, df_info2
Out[24]:
( 국적코드 국가
0 1001 한국
1 1002 미국
2 1003 인도,
국적코드 인구
0 1001 100
1 1001 200
2 1005 300)
In [32]:
### 국적 코드가 같은 값들에 대해서 합치기
# 기준은 df_info1
pd.merge(left=df_info1, right =df_info2, how="inner", left_on="국적코드", right_on="국적코드")
Out[32]:
국적코드 | 국가 | 인구 | |
---|---|---|---|
0 | 1001 | 한국 | 100 |
1 | 1001 | 한국 | 200 |
In [33]:
### 국적 코드가 같은 값은 같은대로, 같지 않으면 NaN으로 합치기 대해서 합치기
# 기준은 df_info1
pd.merge(left=df_info1, right =df_info2, how="left", left_on="국적코드", right_on="국적코드")
Out[33]:
국적코드 | 국가 | 인구 | |
---|---|---|---|
0 | 1001 | 한국 | 100.0 |
1 | 1001 | 한국 | 200.0 |
2 | 1002 | 미국 | NaN |
3 | 1003 | 인도 | NaN |
In [34]:
### 국적 코드가 같은 값은 같은대로, 같지 않으면 NaN으로 합치기 대해서 합치기
# 기준은 df_info2
pd.merge(left=df_info1, right =df_info2, how="right", left_on="국적코드", right_on="국적코드")
Out[34]:
국적코드 | 국가 | 인구 | |
---|---|---|---|
0 | 1001 | 한국 | 100 |
1 | 1001 | 한국 | 200 |
2 | 1005 | NaN | 300 |
전처리¶
<결측치 처리>
In [38]:
### bicycle.csv 파일 읽어오기
df = pd.read_csv("./data/bicycle.csv", encoding="euc-kr")
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 420 entries, 0 to 419
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 자전거번호 420 non-null object
1 대여일시 420 non-null object
2 대여소번호 420 non-null int64
3 대여소명 420 non-null object
4 대여거치대 396 non-null float64
5 반납일시 420 non-null object
6 반납대여소번호 420 non-null int64
7 반납대여소명 420 non-null object
8 반납거치대 409 non-null float64
9 이용시간 405 non-null float64
10 이용거리 404 non-null float64
dtypes: float64(4), int64(2), object(5)
memory usage: 36.2+ KB
In [39]:
### 결측치 데이터 확인하기
# 결측 데이터 값은 True , 정상 데이터 값은 False
df.isnull()
Out[39]:
자전거번호 | 대여일시 | 대여소번호 | 대여소명 | 대여거치대 | 반납일시 | 반납대여소번호 | 반납대여소명 | 반납거치대 | 이용시간 | 이용거리 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | False | False | False | False | False | False | False | False | False | False | False |
1 | False | False | False | False | False | False | False | False | False | False | False |
2 | False | False | False | False | False | False | False | False | False | False | True |
3 | False | False | False | False | False | False | False | False | True | False | False |
4 | False | False | False | False | False | False | False | False | False | False | False |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
415 | False | False | False | False | False | False | False | False | False | False | False |
416 | False | False | False | False | False | False | False | False | True | False | True |
417 | False | False | False | False | False | False | False | False | False | False | False |
418 | False | False | False | False | False | False | False | False | False | False | False |
419 | False | False | False | False | False | False | False | False | False | False | False |
420 rows × 11 columns
In [40]:
### 결측치가 아닌 데이터 확인하기
df.notnull()
Out[40]:
자전거번호 | 대여일시 | 대여소번호 | 대여소명 | 대여거치대 | 반납일시 | 반납대여소번호 | 반납대여소명 | 반납거치대 | 이용시간 | 이용거리 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | True | True | True | True | True | True | True | True | True | True | True |
1 | True | True | True | True | True | True | True | True | True | True | True |
2 | True | True | True | True | True | True | True | True | True | True | False |
3 | True | True | True | True | True | True | True | True | False | True | True |
4 | True | True | True | True | True | True | True | True | True | True | True |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
415 | True | True | True | True | True | True | True | True | True | True | True |
416 | True | True | True | True | True | True | True | True | False | True | False |
417 | True | True | True | True | True | True | True | True | True | True | True |
418 | True | True | True | True | True | True | True | True | True | True | True |
419 | True | True | True | True | True | True | True | True | True | True | True |
420 rows × 11 columns
In [41]:
# 남자 여자 : 범주
# 키 :연속형
"""
<결측치 처리 방법>
1. 결측치가 있는 부분의 데이터를 사용할지 / 말지 결정
2. 사용 안한다면 -> 칼럼과 행 중 어느 부분을 제거할 지 결정
3. 사용한다면 -> 어떻게 대체할지 결정
(대체방법) 우선 사용자에게 어찌할지 물어본다. 1/3/(5)
3.1 결측치가 있는 해당 컬럼의 평균으로 모두 대체
3.2 범주형 데이터인 경우 범주의 비율대비로 대체
3.3 숫자값인 경우 모두 0으로 대체
3.4 결측 데이터가 속한 주변 컬럼들의 데이터 유형과 휴사한 데이터들의 평균으로 대체
3.5 결측치가잇는컬럼의 직전/직후 데이터 평균으로 대체
"""
Out[41]:
'\n<결측치 처리 방법>\n1. 결측치가 있는 부분의 데이터를 사용할지 / 말지 결정\n2. 사용 안한다면 -> 칼럼과 행 중 어느 부분을 제거할 지 결정\n3. 사용한다면 -> 어떻게 대체할지 결정\n(대체방법) 우선 사용자에게 어찌할지 물어본다. 1/3/(5)\n3.1 결측치가 있는 해당 컬럼의 평균으로 모두 대체\n3.2 범주형 데이터인 경우 범주의 비율대비로 대체\n3.3 숫자값인 경우 모두 0으로 대체\n3.4 결측 데이터가 속한 주변 컬럼들의 데이터 유형과 휴사한 데이터들의 평균으로 대체\n3.5 결측치가잇는컬럼의 직전/직후 데이터 평균으로 대체\n'
In [45]:
### 결측데이터 현황 확인
# 컬럼별 결측 현황
# sum(0):0의 의미는 각열의 행 단위를 의미함
df.isnull().sum(0)
Out[45]:
자전거번호 0
대여일시 0
대여소번호 0
대여소명 0
대여거치대 24
반납일시 0
반납대여소번호 0
반납대여소명 0
반납거치대 11
이용시간 15
이용거리 16
dtype: int64
In [47]:
### 결측데이터 현황 확인
# 컬럼별 결측 현황
# sum(1):1의 의미는 각행의 칼럼 단위를 의미함
df.isnull().sum(1)
Out[47]:
0 0
1 0
2 1
3 1
4 0
..
415 0
416 2
417 0
418 0
419 0
Length: 420, dtype: int64
결측데이터 삭제하기¶
In [55]:
### 결측치가 있는 모든 행들 삭제하기
df_drop=df.dropna(axis=0)
df_drop
Out[55]:
자전거번호 | 대여일시 | 대여소번호 | 대여소명 | 대여거치대 | 반납일시 | 반납대여소번호 | 반납대여소명 | 반납거치대 | 이용시간 | 이용거리 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | SPB-23220 | 2019-11-01 8:48 | 646 | 장한평역 1번출구 (국민은행앞) | 3.0 | 2019-11-01 9:01 | 3 | 중랑센터 | 7.0 | 12.0 | 1100.0 |
1 | SPB-16216 | 2019-11-04 8:38 | 646 | 장한평역 1번출구 (국민은행앞) | 2.0 | 2019-11-04 8:56 | 3 | 중랑센터 | 2.0 | 7.0 | 1420.0 |
4 | SPB-07935 | 2019-11-05 12:29 | 512 | 뚝섬역 1번 출구 옆 | 11.0 | 2019-11-05 12:39 | 3 | 중랑센터 | 7.0 | 10.0 | 1650.0 |
5 | SPB-18401 | 2019-11-06 8:52 | 646 | 장한평역 1번출구 (국민은행앞) | 1.0 | 2019-11-06 9:09 | 3 | 중랑센터 | 7.0 | 11.0 | 1350.0 |
6 | SPB-18350 | 2019-11-06 8:35 | 646 | 장한평역 1번출구 (국민은행앞) | 1.0 | 2019-11-06 9:10 | 3 | 중랑센터 | 2.0 | 9.0 | 1390.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
414 | SPB-24515 | 2019-11-15 3:58 | 112 | 극동방송국 앞 | 1.0 | 2019-11-15 4:08 | 101 | (구)합정동 주민센터 | 1.0 | 9.0 | 1620.0 |
415 | SPB-12116 | 2019-11-15 4:22 | 112 | 극동방송국 앞 | 5.0 | 2019-11-15 4:33 | 101 | (구)합정동 주민센터 | 1.0 | 11.0 | 2200.0 |
417 | SPB-18841 | 2019-11-15 20:40 | 113 | 홍대입구역 2번출구 앞 | 24.0 | 2019-11-15 20:53 | 101 | (구)합정동 주민센터 | 1.0 | 12.0 | 2280.0 |
418 | SPB-24467 | 2019-11-15 21:55 | 152 | 마포구민체육센터 앞 | 18.0 | 2019-11-15 22:05 | 101 | (구)합정동 주민센터 | 1.0 | 10.0 | 1180.0 |
419 | SPB-17570 | 2019-11-15 22:16 | 391 | 정동길입구 | 7.0 | 2019-11-15 23:04 | 101 | (구)합정동 주민센터 | 5.0 | 48.0 | 8100.0 |
358 rows × 11 columns
In [56]:
### 결측치가 있는 모든 컬럼들 삭제하기
df_drop=df.dropna(axis=1)
df_drop
Out[56]:
자전거번호 | 대여일시 | 대여소번호 | 대여소명 | 대여거치대 | 반납일시 | 반납대여소번호 | 반납대여소명 | 반납거치대 | 이용시간 | 이용거리 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | SPB-23220 | 2019-11-01 8:48 | 646 | 장한평역 1번출구 (국민은행앞) | 3.0 | 2019-11-01 9:01 | 3 | 중랑센터 | 7.0 | 12.0 | 1100.0 |
1 | SPB-16216 | 2019-11-04 8:38 | 646 | 장한평역 1번출구 (국민은행앞) | 2.0 | 2019-11-04 8:56 | 3 | 중랑센터 | 2.0 | 7.0 | 1420.0 |
4 | SPB-07935 | 2019-11-05 12:29 | 512 | 뚝섬역 1번 출구 옆 | 11.0 | 2019-11-05 12:39 | 3 | 중랑센터 | 7.0 | 10.0 | 1650.0 |
5 | SPB-18401 | 2019-11-06 8:52 | 646 | 장한평역 1번출구 (국민은행앞) | 1.0 | 2019-11-06 9:09 | 3 | 중랑센터 | 7.0 | 11.0 | 1350.0 |
6 | SPB-18350 | 2019-11-06 8:35 | 646 | 장한평역 1번출구 (국민은행앞) | 1.0 | 2019-11-06 9:10 | 3 | 중랑센터 | 2.0 | 9.0 | 1390.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
414 | SPB-24515 | 2019-11-15 3:58 | 112 | 극동방송국 앞 | 1.0 | 2019-11-15 4:08 | 101 | (구)합정동 주민센터 | 1.0 | 9.0 | 1620.0 |
415 | SPB-12116 | 2019-11-15 4:22 | 112 | 극동방송국 앞 | 5.0 | 2019-11-15 4:33 | 101 | (구)합정동 주민센터 | 1.0 | 11.0 | 2200.0 |
417 | SPB-18841 | 2019-11-15 20:40 | 113 | 홍대입구역 2번출구 앞 | 24.0 | 2019-11-15 20:53 | 101 | (구)합정동 주민센터 | 1.0 | 12.0 | 2280.0 |
418 | SPB-24467 | 2019-11-15 21:55 | 152 | 마포구민체육센터 앞 | 18.0 | 2019-11-15 22:05 | 101 | (구)합정동 주민센터 | 1.0 | 10.0 | 1180.0 |
419 | SPB-17570 | 2019-11-15 22:16 | 391 | 정동길입구 | 7.0 | 2019-11-15 23:04 | 101 | (구)합정동 주민센터 | 5.0 | 48.0 | 8100.0 |
358 rows × 11 columns
In [61]:
df["이용거리"].fillna(0) # null 을 0으로 바꾼다.
# df["이용거리"].fillna("missing") # null 을 0으로 바꾼다.
df["이용거리"].fillna(df["이용거리"].mean())
Out[61]:
0 1100.000000
1 1420.000000
2 2679.678218
3 1380.000000
4 1650.000000
...
415 2200.000000
416 2679.678218
417 2280.000000
418 1180.000000
419 8100.000000
Name: 이용거리, Length: 420, dtype: float64
중복데이터¶
In [74]:
df["이용거리"]
### 중복데이터가 행의 위치 확인하기
df[df.duplicated(["이용거리"])] # 중복된 데이터들의 정보가 나온다.
### keep : 중복 중에 몇 번째 중복을 False(남겨둘것인지)로 할것인지
### 중복 중에 첫번째는 False, 나머지는 뒤에 중복들은 모두 True로
# keep : first , last, False
# first : 첫번째만 False(뒤쪽 중복데이터는 모두 True) -> 기본값 생략가능
# last : 마지막만 False (앞쪽 중복데이터는 모두 True)
# False: 중복 데이터 전체 True
df.duplicated(["이용거리"], keep="first")
df.duplicated(["이용거리"], keep="last")
df.duplicated(["이용거리"], keep=False)
df_no_duplicates = df[~df.duplicated(["이용거리"])] # 중복된 데이터 제외하고 출
print(df.duplicated(["이용거리"]) )
df.duplicated(["이용거리"],keep="first").value_counts()
0 False
1 False
2 False
3 False
4 False
...
415 False
416 True
417 True
418 True
419 False
Length: 420, dtype: bool
Out[74]:
False 258
True 162
Name: count, dtype: int64
In [73]:
### 중복데이터는 사용할지 말지만 결정하면 됩니다.
# 원래는 전체 열에서 중복검사를 한다.
df.drop_duplicates(["이용거리"])
Out[73]:
자전거번호 | 대여일시 | 대여소번호 | 대여소명 | 대여거치대 | 반납일시 | 반납대여소번호 | 반납대여소명 | 반납거치대 | 이용시간 | 이용거리 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | SPB-23220 | 2019-11-01 8:48 | 646 | 장한평역 1번출구 (국민은행앞) | 3.0 | 2019-11-01 9:01 | 3 | 중랑센터 | 7.0 | 12.0 | 1100.0 |
1 | SPB-16216 | 2019-11-04 8:38 | 646 | 장한평역 1번출구 (국민은행앞) | 2.0 | 2019-11-04 8:56 | 3 | 중랑센터 | 2.0 | 7.0 | 1420.0 |
2 | SPB-21097 | 2019-11-04 8:46 | 646 | 장한평역 1번출구 (국민은행앞) | 1.0 | 2019-11-04 8:57 | 3 | 중랑센터 | 7.0 | 10.0 | NaN |
3 | SPB-22292 | 2019-11-05 8:34 | 646 | 장한평역 1번출구 (국민은행앞) | 1.0 | 2019-11-05 8:45 | 3 | 중랑센터 | NaN | 10.0 | 1380.0 |
4 | SPB-07935 | 2019-11-05 12:29 | 512 | 뚝섬역 1번 출구 옆 | 11.0 | 2019-11-05 12:39 | 3 | 중랑센터 | 7.0 | 10.0 | 1650.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
410 | SPB-18614 | 2019-11-14 23:07 | 391 | 정동길입구 | 5.0 | 2019-11-14 23:49 | 101 | (구)합정동 주민센터 | 3.0 | 40.0 | 7510.0 |
413 | SPB-25161 | 2019-11-15 3:13 | 106 | 합정역 7번출구 앞 | 6.0 | 2019-11-15 3:18 | 101 | (구)합정동 주민센터 | 1.0 | 3.0 | 640.0 |
414 | SPB-24515 | 2019-11-15 3:58 | 112 | 극동방송국 앞 | 1.0 | 2019-11-15 4:08 | 101 | (구)합정동 주민센터 | 1.0 | 9.0 | 1620.0 |
415 | SPB-12116 | 2019-11-15 4:22 | 112 | 극동방송국 앞 | 5.0 | 2019-11-15 4:33 | 101 | (구)합정동 주민센터 | 1.0 | 11.0 | 2200.0 |
419 | SPB-17570 | 2019-11-15 22:16 | 391 | 정동길입구 | 7.0 | 2019-11-15 23:04 | 101 | (구)합정동 주민센터 | 5.0 | 48.0 | 8100.0 |
258 rows × 11 columns
이상데이터 처리하기¶
In [76]:
"""
이상 데이터 처리순서
1.결측치 처리가 선행되어야 합니다
-결측치도 데이터로 인식되기 때문에..
2.이상데이터는 범주형, 숫자형 데이터 처리방식이 다름
-일반적으로 이상데이터는 숫자형 데이터 처리를 주로 합니다.
3.이상 데이터 확인은 시각화(boxplot)를 통해서 확인합니다.
4. 실제 처리는 계산에 의해 처리됩니다.
"""
Out[76]:
'\n이상 데이터 처리순서\n1.결측치 처리가 선행되어야 합니다\n-결측치도 데이터로 인식되기 때문에..\n2.이상데이터는 범주형, 숫자형 데이터 처리방식이 다름\n-일반적으로 이상데이터는 숫자형 데이터 처리를 주로 합니다.\n3.이상 데이터 확인은 시각화(boxplot)를 통해서 확인합니다.\n4. 실제 처리는 계산에 의해 처리됩니다.\n'
In [77]:
### 시각화 라이브러리
import matplotlib.pylab as plt
In [79]:
### 사용할 데이터 읽어 들이기
df = pd.read_csv("./data/bicycle_out.csv", encoding="euc_kr")
In [80]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 420 entries, 0 to 419
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 자전거번호 420 non-null object
1 대여일시 420 non-null object
2 대여소번호 420 non-null int64
3 대여소명 420 non-null object
4 대여거치대 396 non-null float64
5 반납일시 420 non-null object
6 반납대여소번호 420 non-null int64
7 반납대여소명 420 non-null object
8 반납거치대 409 non-null float64
9 이용시간 405 non-null float64
10 이용거리 404 non-null float64
11 나이 420 non-null int64
dtypes: float64(4), int64(3), object(5)
memory usage: 39.5+ KB
In [84]:
### 결측치 처리하기
df["대여거치대"] = df["대여거치대"].fillna(int(df["대여거치대"].mean()))
df["반납거치대"] = df["반납거치대"].fillna(int(df["반납거치대"].mean()))
df["이용시간"] = df["이용시간"].fillna(int(df["이용시간"].mean()))
df["이용거리"] = df["이용거리"].fillna(int(df["이용거리"].mean()))
In [85]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 420 entries, 0 to 419
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 자전거번호 420 non-null object
1 대여일시 420 non-null object
2 대여소번호 420 non-null int64
3 대여소명 420 non-null object
4 대여거치대 420 non-null float64
5 반납일시 420 non-null object
6 반납대여소번호 420 non-null int64
7 반납대여소명 420 non-null object
8 반납거치대 420 non-null float64
9 이용시간 420 non-null float64
10 이용거리 420 non-null float64
11 나이 420 non-null int64
dtypes: float64(4), int64(3), object(5)
memory usage: 39.5+ KB
In [87]:
## 행단위 중복 체크
df.duplicated().value_counts()
Out[87]:
False 420
Name: count, dtype: int64
In [88]:
### 이상 데이터 확인하기
df.describe()
Out[88]:
대여소번호 | 대여거치대 | 반납대여소번호 | 반납거치대 | 이용시간 | 이용거리 | 나이 | |
---|---|---|---|---|---|---|---|
count | 420.000000 | 420.000000 | 420.000000 | 420.000000 | 420.000000 | 420.000000 | 420.000000 |
mean | 243.254762 | 7.552381 | 93.338095 | 2.809524 | 21.259524 | 2679.652381 | 35.445238 |
std | 301.148255 | 6.078611 | 26.270667 | 1.670152 | 19.871587 | 2969.890938 | 31.823039 |
min | 3.000000 | 1.000000 | 3.000000 | 1.000000 | 2.000000 | 0.000000 | 21.000000 |
25% | 104.000000 | 3.000000 | 101.000000 | 1.000000 | 8.000000 | 1070.000000 | 24.000000 |
50% | 117.500000 | 6.000000 | 101.000000 | 2.000000 | 15.000000 | 1760.000000 | 29.000000 |
75% | 226.500000 | 10.000000 | 101.000000 | 4.000000 | 27.000000 | 3547.500000 | 40.000000 |
max | 3102.000000 | 30.000000 | 101.000000 | 7.000000 | 122.000000 | 42070.000000 | 533.000000 |
In [91]:
### 나이 데이터를 기준으로 이상데이터 시각적으로 확인하기
## 박스플롯 (boxplot)
#이 함수는 데이터의 중앙값, 사분위 범위(IQR), 특이치(outlier) 등을 시각적으로 보여줍니다.
#상자그림은 데이터의 중심 경향과 분산을 파악하는 데 유용하며, 이상치나 특이치가 있는지도 시각적으로 확인할 수 있습니다
## outliner
plt.boxplot(df["나이"])
plt.show()
"""
박스 위쪽 선: Max Outliers
박스 하단 선: Mix Outliers
이상치로 의심되는 데이터 : Max 및 Min Outliers를 벗어난 데이터들
"""
In [93]:
## 100살 이상 데이터 확인하기
(df["나이"]>=100).value_counts()
Out[93]:
나이
False 416
True 4
Name: count, dtype: int64
In [94]:
df.describe()
Out[94]:
대여소번호 | 대여거치대 | 반납대여소번호 | 반납거치대 | 이용시간 | 이용거리 | 나이 | |
---|---|---|---|---|---|---|---|
count | 420.000000 | 420.000000 | 420.000000 | 420.000000 | 420.000000 | 420.000000 | 420.000000 |
mean | 243.254762 | 7.552381 | 93.338095 | 2.809524 | 21.259524 | 2679.652381 | 35.445238 |
std | 301.148255 | 6.078611 | 26.270667 | 1.670152 | 19.871587 | 2969.890938 | 31.823039 |
min | 3.000000 | 1.000000 | 3.000000 | 1.000000 | 2.000000 | 0.000000 | 21.000000 |
25% | 104.000000 | 3.000000 | 101.000000 | 1.000000 | 8.000000 | 1070.000000 | 24.000000 |
50% | 117.500000 | 6.000000 | 101.000000 | 2.000000 | 15.000000 | 1760.000000 | 29.000000 |
75% | 226.500000 | 10.000000 | 101.000000 | 4.000000 | 27.000000 | 3547.500000 | 40.000000 |
max | 3102.000000 | 30.000000 | 101.000000 | 7.000000 | 122.000000 | 42070.000000 | 533.000000 |
In [95]:
### 이상치 계산 공식
# 최대 = q3 +(1.5 * IQR)
# 최소 = q1 -(1.5 * IQR)
In [97]:
import numpy as np
In [100]:
### 25% 및 75% 시점의 값 추출하기
q1, q3 = np.percentile(df["나이"],[25,75])
q1,q3
Out[100]:
(24.0, 40.0)
In [101]:
### IQR 계산
iqr = q3-q1
iqr
Out[101]:
16.0
In [102]:
### max outlier 계산
upper_bound= q3 + (1.5*iqr)
upper_bound
Out[102]:
64.0
In [103]:
### min outlier 계산
lower_bound = q1-(1.5 *iqr)
upper_bound, lower_bound
Out[103]:
(64.0, 0.0)
In [109]:
### 이상치로 의심되는 max 또는 min을 벗어나는 데이터 추출하기
df[((df["나이"]>upper_bound) | (df["나이"]<lower_bound))]
# 이상치를 찾기 위한 조건
df[(df["나이"] > upper_bound) | (df["나이"]<lower_bound)]
Out[109]:
자전거번호 | 대여일시 | 대여소번호 | 대여소명 | 대여거치대 | 반납일시 | 반납대여소번호 | 반납대여소명 | 반납거치대 | 이용시간 | 이용거리 | 나이 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
4 | SPB-07935 | 2019-11-05 12:29 | 512 | 뚝섬역 1번 출구 옆 | 11.0 | 2019-11-05 12:39 | 3 | 중랑센터 | 7.0 | 10.0 | 1650.0 | 120 |
30 | SPB-20840 | 2019-11-28 8:32 | 419 | 홈플러스 앞 | 1.0 | 2019-11-28 8:35 | 5 | 상암센터 정비실 | 5.0 | 3.0 | 280.0 | 533 |
47 | SPB-11637 | 2019-11-01 15:35 | 103 | 망원역 2번출구 앞 | 4.0 | 2019-11-01 15:41 | 101 | (구)합정동 주민센터 | 2.0 | 5.0 | 1110.0 | 320 |
86 | SPB-04854 | 2019-11-02 19:52 | 101 | (구)합정동 주민센터 | 5.0 | 2019-11-02 21:01 | 101 | (구)합정동 주민센터 | 2.0 | 21.0 | 2300.0 | 220 |
123 | SPB-22075 | 2019-11-03 21:50 | 152 | 마포구민체육센터 앞 | 7.0 | 2019-11-03 21:57 | 101 | (구)합정동 주민센터 | 1.0 | 6.0 | 970.0 | 69 |
148 | SPB-24758 | 2019-11-04 17:59 | 106 | 합정역 7번출구 앞 | 7.0 | 2019-11-04 18:20 | 101 | (구)합정동 주민센터 | 5.0 | 20.0 | 1130.0 | 65 |
221 | SPB-06127 | 2019-11-06 16:06 | 1925 | 동양미래대학교 정문 옆 | 6.0 | 2019-11-06 17:09 | 101 | (구)합정동 주민센터 | 4.0 | 62.0 | 12610.0 | 66 |
294 | SPB-08818 | 2019-11-08 23:13 | 108 | 서교동 사거리 | 2.0 | 2019-11-08 23:24 | 101 | (구)합정동 주민센터 | 2.0 | 10.0 | 1360.0 | 65 |
362 | SPB-24781 | 2019-11-12 10:45 | 101 | (구)합정동 주민센터 | 3.0 | 2019-11-12 11:50 | 101 | (구)합정동 주민센터 | 4.0 | 64.0 | 5600.0 | 65 |
363 | SPB-24858 | 2019-11-12 11:41 | 113 | 홍대입구역 2번출구 앞 | 21.0 | 2019-11-12 11:54 | 101 | (구)합정동 주민센터 | 1.0 | 11.0 | 2060.0 | 67 |
In [ ]:
728x90
반응형