모듈 import¶
!pip install seaborn==0.13.0
Defaulting to user installation because normal site-packages is not writeable Collecting seaborn==0.13.0 Downloading seaborn-0.13.0-py3-none-any.whl (294 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 294.6/294.6 kB 6.6 MB/s eta 0:00:00a 0:00:01 Requirement already satisfied: numpy!=1.24.0,>=1.20 in ./.local/lib/python3.9/site-packages (from seaborn==0.13.0) (1.23.3) Requirement already satisfied: pandas>=1.2 in ./.local/lib/python3.9/site-packages (from seaborn==0.13.0) (1.4.2) Requirement already satisfied: matplotlib!=3.6.1,>=3.3 in ./.local/lib/python3.9/site-packages (from seaborn==0.13.0) (3.6.0) Requirement already satisfied: pyparsing>=2.2.1 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (3.0.9) Requirement already satisfied: contourpy>=1.0.1 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (1.0.6) Requirement already satisfied: fonttools>=4.22.0 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (4.38.0) Requirement already satisfied: cycler>=0.10 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (0.11.0) Requirement already satisfied: pillow>=6.2.0 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (9.3.0) Requirement already satisfied: kiwisolver>=1.0.1 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (1.4.4) Requirement already satisfied: python-dateutil>=2.7 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (2.8.2) Requirement already satisfied: packaging>=20.0 in ./.local/lib/python3.9/site-packages (from matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (21.3) Requirement already satisfied: pytz>=2020.1 in ./.local/lib/python3.9/site-packages (from pandas>=1.2->seaborn==0.13.0) (2022.5) Requirement already satisfied: six>=1.5 in ./.local/lib/python3.9/site-packages (from python-dateutil>=2.7->matplotlib!=3.6.1,>=3.3->seaborn==0.13.0) (1.16.0) Installing collected packages: seaborn Attempting uninstall: seaborn Found existing installation: seaborn 0.12.0 Uninstalling seaborn-0.12.0: Successfully uninstalled seaborn-0.12.0 Successfully installed seaborn-0.13.0 [notice] A new release of pip available: 22.2.2 -> 24.1.1 [notice] To update, run: pip install --upgrade pip
from IPython.display import Image
import numpy as np
import pandas as pd
import seaborn as sns
import warnings
# warning 무시
warnings.filterwarnings('ignore')
# e notation 표현 방식 변경
pd.options.display.float_format = '{:.2f}'.format
# 모든 컬럼 표시
pd.set_option('display.max_columns', None)
데이터셋 로드¶
df = sns.load_dataset('titanic')
df.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True |
3 | 1 | 1 | female | 35.00 | 1 | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True |
컬럼(columns) 설명
- survivied: 생존여부 (1: 생존, 0: 사망)
- pclass: 좌석 등급 (1등급, 2등급, 3등급)
- sex: 성별
- age: 나이
- sibsp: 형제 + 배우자 수
- parch: 부모 + 자녀 수
- fare: 좌석 요금
- embarked: 탑승 항구 (S, C, Q)
- class: pclass와 동일
- who: 남자(man), 여자(woman), 아이(child)
- adult_male: 성인 남자 여부
- deck: 데크 번호 (알파벳 + 숫자 혼용)
- embark_town: 탑승 항구 이름
- alive: 생존여부 (yes, no)
- alone: 혼자 탑승 여부
새로운 컬럼 추가¶
df1 = df.copy()
df1.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True |
3 | 1 | 1 | female | 35.00 | 1 | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True |
임의의 값을 대입하여 새로운 컬럼을 추가할 수 있습니다.
df1['VIP'] = True
df1.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | True |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False | True |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | True |
3 | 1 | 1 | female | 35.00 | 1 | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False | True |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | True |
중간에 컬럼을 추가하고 싶은 경우 insert()
를 활용할 수 있습니다.
insert(컬럼인덱스, 컬럼명, 값)
df1.insert(5, 'RICH', df1['fare'] > 100)
df1.head()
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | True |
1 | 1 | 1 | female | 38.00 | 1 | False | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | True |
3 | 1 | 1 | female | 35.00 | 1 | False | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | True |
삭제¶
삭제는 행(row) 삭제와 열(column) 삭제로 구분할 수 있습니다.
행 (row) 삭제¶
행 삭제시 index를 지정하여 삭제합니다.
df1.drop(1)
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | True |
3 | 1 | 1 | female | 35.00 | 1 | False | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | True |
5 | 0 | 3 | male | NaN | 0 | False | 0 | 8.46 | Q | Third | man | True | NaN | Queenstown | no | True | True |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
886 | 0 | 2 | male | 27.00 | 0 | False | 0 | 13.00 | S | Second | man | True | NaN | Southampton | no | True | True |
887 | 1 | 1 | female | 19.00 | 0 | False | 0 | 30.00 | S | First | woman | False | B | Southampton | yes | True | True |
888 | 0 | 3 | female | NaN | 1 | False | 2 | 23.45 | S | Third | woman | False | NaN | Southampton | no | False | True |
889 | 1 | 1 | male | 26.00 | 0 | False | 0 | 30.00 | C | First | man | True | C | Cherbourg | yes | True | True |
890 | 0 | 3 | male | 32.00 | 0 | False | 0 | 7.75 | Q | Third | man | True | NaN | Queenstown | no | True | True |
890 rows × 17 columns
행 삭제시 범위를 지정하여 삭제할 수 있습니다.
df1.drop(np.arange(10))
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
10 | 1 | 3 | female | 4.00 | 1 | False | 1 | 16.70 | S | Third | child | False | G | Southampton | yes | False | True |
11 | 1 | 1 | female | 58.00 | 0 | False | 0 | 26.55 | S | First | woman | False | C | Southampton | yes | True | True |
12 | 0 | 3 | male | 20.00 | 0 | False | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | True |
13 | 0 | 3 | male | 39.00 | 1 | False | 5 | 31.27 | S | Third | man | True | NaN | Southampton | no | False | True |
14 | 0 | 3 | female | 14.00 | 0 | False | 0 | 7.85 | S | Third | child | False | NaN | Southampton | no | True | True |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
886 | 0 | 2 | male | 27.00 | 0 | False | 0 | 13.00 | S | Second | man | True | NaN | Southampton | no | True | True |
887 | 1 | 1 | female | 19.00 | 0 | False | 0 | 30.00 | S | First | woman | False | B | Southampton | yes | True | True |
888 | 0 | 3 | female | NaN | 1 | False | 2 | 23.45 | S | Third | woman | False | NaN | Southampton | no | False | True |
889 | 1 | 1 | male | 26.00 | 0 | False | 0 | 30.00 | C | First | man | True | C | Cherbourg | yes | True | True |
890 | 0 | 3 | male | 32.00 | 0 | False | 0 | 7.75 | Q | Third | man | True | NaN | Queenstown | no | True | True |
881 rows × 17 columns
fancy indexing을 활용하여 삭제할 수 있습니다.
df1.drop([1, 3, 5, 7, 9])
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | True |
6 | 0 | 1 | male | 54.00 | 0 | False | 0 | 51.86 | S | First | man | True | E | Southampton | no | True | True |
8 | 1 | 3 | female | 27.00 | 0 | False | 2 | 11.13 | S | Third | woman | False | NaN | Southampton | yes | False | True |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
886 | 0 | 2 | male | 27.00 | 0 | False | 0 | 13.00 | S | Second | man | True | NaN | Southampton | no | True | True |
887 | 1 | 1 | female | 19.00 | 0 | False | 0 | 30.00 | S | First | woman | False | B | Southampton | yes | True | True |
888 | 0 | 3 | female | NaN | 1 | False | 2 | 23.45 | S | Third | woman | False | NaN | Southampton | no | False | True |
889 | 1 | 1 | male | 26.00 | 0 | False | 0 | 30.00 | C | First | man | True | C | Cherbourg | yes | True | True |
890 | 0 | 3 | male | 32.00 | 0 | False | 0 | 7.75 | Q | Third | man | True | NaN | Queenstown | no | True | True |
886 rows × 17 columns
열 (column) 삭제¶
df1.head()
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | True |
1 | 1 | 1 | female | 38.00 | 1 | False | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | True |
3 | 1 | 1 | female | 35.00 | 1 | False | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | True |
열 삭제시 반드시 axis=1
옵션을 지정해야 합니다. 2번째 위치에 지정시 axis=
을 생략할 수 있습니다.
df1.drop('class', axis=1).head()
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | man | True | NaN | Southampton | no | False | True |
1 | 1 | 1 | female | 38.00 | 1 | False | 0 | 71.28 | C | woman | False | C | Cherbourg | yes | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | woman | False | NaN | Southampton | yes | True | True |
3 | 1 | 1 | female | 35.00 | 1 | False | 0 | 53.10 | S | woman | False | C | Southampton | yes | False | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | man | True | NaN | Southampton | no | True | True |
df1.drop('class', 1).head()
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | who | adult_male | deck | embark_town | alive | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | man | True | NaN | Southampton | no | False | True |
1 | 1 | 1 | female | 38.00 | 1 | False | 0 | 71.28 | C | woman | False | C | Cherbourg | yes | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | woman | False | NaN | Southampton | yes | True | True |
3 | 1 | 1 | female | 35.00 | 1 | False | 0 | 53.10 | S | woman | False | C | Southampton | yes | False | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | man | True | NaN | Southampton | no | True | True |
다수의 컬럼(column) 삭제도 가능합니다.
df1.drop(['who', 'deck', 'alive'], axis=1)
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | class | adult_male | embark_town | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | Third | True | Southampton | False | True |
1 | 1 | 1 | female | 38.00 | 1 | False | 0 | 71.28 | C | First | False | Cherbourg | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | Third | False | Southampton | True | True |
3 | 1 | 1 | female | 35.00 | 1 | False | 0 | 53.10 | S | First | False | Southampton | False | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | Third | True | Southampton | True | True |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
886 | 0 | 2 | male | 27.00 | 0 | False | 0 | 13.00 | S | Second | True | Southampton | True | True |
887 | 1 | 1 | female | 19.00 | 0 | False | 0 | 30.00 | S | First | False | Southampton | True | True |
888 | 0 | 3 | female | NaN | 1 | False | 2 | 23.45 | S | Third | False | Southampton | False | True |
889 | 1 | 1 | male | 26.00 | 0 | False | 0 | 30.00 | C | First | True | Cherbourg | True | True |
890 | 0 | 3 | male | 32.00 | 0 | False | 0 | 7.75 | Q | Third | True | Queenstown | True | True |
891 rows × 14 columns
삭제된 내용을 바로 적용하려면
inplace=True
를 지정합니다.- 변수에 재대입 하여 결과를 반영합니다.
df1.drop(['who', 'deck', 'alive'], axis=1, inplace=True)
df1.head()
survived | pclass | sex | age | sibsp | RICH | parch | fare | embarked | class | adult_male | embark_town | alone | VIP | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | False | 0 | 7.25 | S | Third | True | Southampton | False | True |
1 | 1 | 1 | female | 38.00 | 1 | False | 0 | 71.28 | C | First | False | Cherbourg | False | True |
2 | 1 | 3 | female | 26.00 | 0 | False | 0 | 7.92 | S | Third | False | Southampton | True | True |
3 | 1 | 1 | female | 35.00 | 1 | False | 0 | 53.10 | S | First | False | Southampton | False | True |
4 | 0 | 3 | male | 35.00 | 0 | False | 0 | 8.05 | S | Third | True | Southampton | True | True |
연습문제¶
df1
에서 1, 3, 5번행을 삭제해 주세요df1
에서embarked
,class
,alone
컬럼을 삭제해 주세요df1
의 상위 10개 행을 출력하세요
# df 데이터프레임 복제
df1 = df.copy()
# 코드를 입력해 주세요
# 1, 3, 5번 행 삭제
df1 = df1.drop([1, 3, 5])
# 'embarked', 'class', 'alone' 컬럼 삭제
df1 = df1.drop(columns=['embarked', 'class', 'alone'])
# 상위 10개 행 출력
df1.head(10)
survived | pclass | sex | age | sibsp | parch | fare | who | adult_male | deck | embark_town | alive | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | man | True | NaN | Southampton | no |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | woman | False | NaN | Southampton | yes |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | man | True | NaN | Southampton | no |
6 | 0 | 1 | male | 54.00 | 0 | 0 | 51.86 | man | True | E | Southampton | no |
7 | 0 | 3 | male | 2.00 | 3 | 1 | 21.07 | child | False | NaN | Southampton | no |
8 | 1 | 3 | female | 27.00 | 0 | 2 | 11.13 | woman | False | NaN | Southampton | yes |
9 | 1 | 2 | female | 14.00 | 1 | 0 | 30.07 | child | False | NaN | Cherbourg | yes |
10 | 1 | 3 | female | 4.00 | 1 | 1 | 16.70 | child | False | G | Southampton | yes |
11 | 1 | 1 | female | 58.00 | 0 | 0 | 26.55 | woman | False | C | Southampton | yes |
12 | 0 | 3 | male | 20.00 | 0 | 0 | 8.05 | man | True | NaN | Southampton | no |
[출력 결과]
survived | pclass | sex | age | sibsp | parch | fare | who | adult_male | deck | embark_town | alive | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | man | True | NaN | Southampton | no |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | woman | False | NaN | Southampton | yes |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | man | True | NaN | Southampton | no |
6 | 0 | 1 | male | 54.00 | 0 | 0 | 51.86 | man | True | E | Southampton | no |
7 | 0 | 3 | male | 2.00 | 3 | 1 | 21.07 | child | False | NaN | Southampton | no |
8 | 1 | 3 | female | 27.00 | 0 | 2 | 11.13 | woman | False | NaN | Southampton | yes |
9 | 1 | 2 | female | 14.00 | 1 | 0 | 30.07 | child | False | NaN | Cherbourg | yes |
10 | 1 | 3 | female | 4.00 | 1 | 1 | 16.70 | child | False | G | Southampton | yes |
11 | 1 | 1 | female | 58.00 | 0 | 0 | 26.55 | woman | False | C | Southampton | yes |
12 | 0 | 3 | male | 20.00 | 0 | 0 | 8.05 | man | True | NaN | Southampton | no |
컬럼간 연산¶
컬럼(column) 과 컬럼 사이의 연산을 매우 쉽게 적용할 수 있습니다.
# df 데이터프레임 복제
df1 = df.copy()
family(가족)의 총합은 sibsp컬럼과 parch의 합산으로 구할 수 있습니다.
df1['family'] = df1['sibsp'] + df1['parch']
df1.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | family | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | 1 |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False | 1 |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | 0 |
3 | 1 | 1 | female | 35.00 | 1 | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False | 1 |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | 0 |
문자열의 합 (이어붙히기)도 가능합니다.
df1['gender'] = df1['who'] + '-' + df1['sex']
df1.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | family | gender | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | 1 | man-male |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False | 1 | woman-female |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | 0 | woman-female |
3 | 1 | 1 | female | 35.00 | 1 | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False | 1 | woman-female |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | 0 | man-male |
컬럼간 연산시 round()
를 사용하여 소수점 자릿수를 지정할 수 있습니다.
round(숫자, 소수 몇 째자리)
df1['round'] = round(df1['fare'] / df1['age'], 2)
df1.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | family | gender | round | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False | 1 | man-male | 0.33 |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False | 1 | woman-female | 1.88 |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True | 0 | woman-female | 0.30 |
3 | 1 | 1 | female | 35.00 | 1 | 0 | 53.10 | S | First | woman | False | C | Southampton | yes | False | 1 | woman-female | 1.52 |
4 | 0 | 3 | male | 35.00 | 0 | 0 | 8.05 | S | Third | man | True | NaN | Southampton | no | True | 0 | man-male | 0.23 |
연산시 1개의 컬럼이라도 NaN 값을 포함하고 있다면 결과는 NaN 이 됩니다.
df1.loc[df1['age'].isnull(), ['fare', 'age', 'round']].head()
fare | age | round | |
---|---|---|---|
5 | 8.46 | NaN | NaN |
17 | 13.00 | NaN | NaN |
19 | 7.22 | NaN | NaN |
26 | 7.22 | NaN | NaN |
28 | 7.88 | NaN | NaN |
연습문제¶
iris
붓꽃 데이터셋을 활용하여 다음의 문제를 풀어주세요
(참고)
- species: 붓꽃 데이터의 종류
sepal_length
: 꽃받침의 길이sepal_width
: 꽃받침의 넓이petal_length
: 꽃잎의 길이petal_width
: 꽃잎의 넓이
iris = sns.load_dataset('iris')
iris.head()
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.10 | 3.50 | 1.40 | 0.20 | setosa |
1 | 4.90 | 3.00 | 1.40 | 0.20 | setosa |
2 | 4.70 | 3.20 | 1.30 | 0.20 | setosa |
3 | 4.60 | 3.10 | 1.50 | 0.20 | setosa |
4 | 5.00 | 3.60 | 1.40 | 0.20 | setosa |
sepal
컬럼을 생성하고,sepal_length
와sepal_width
를 곱한 값을 대입하세요- 상위 5개 행만 출력해 주세요
# 코드를 입력해 주세요
df1 = iris
df1['sepal'] = df1['sepal_length'] * df1['sepal_width']
# 상위 5개 행 출력
df1.head(5)
sepal_length | sepal_width | petal_length | petal_width | species | sepal | petal | |
---|---|---|---|---|---|---|---|
0 | 5.10 | 3.50 | 1.40 | 0.20 | setosa | 17.85 | 0.28 |
1 | 4.90 | 3.00 | 1.40 | 0.20 | setosa | 14.70 | 0.28 |
2 | 4.70 | 3.20 | 1.30 | 0.20 | setosa | 15.04 | 0.26 |
3 | 4.60 | 3.10 | 1.50 | 0.20 | setosa | 14.26 | 0.30 |
4 | 5.00 | 3.60 | 1.40 | 0.20 | setosa | 18.00 | 0.28 |
[출력 결과]
sepal_length | sepal_width | petal_length | petal_width | species | sepal | |
---|---|---|---|---|---|---|
0 | 5.10 | 3.50 | 1.40 | 0.20 | setosa | 17.85 |
1 | 4.90 | 3.00 | 1.40 | 0.20 | setosa | 14.70 |
2 | 4.70 | 3.20 | 1.30 | 0.20 | setosa | 15.04 |
3 | 4.60 | 3.10 | 1.50 | 0.20 | setosa | 14.26 |
4 | 5.00 | 3.60 | 1.40 | 0.20 | setosa | 18.00 |
petal
컬럼을 생성하고,petal_length
와petal_width
를 곱한 값을 대입하세요- 상위 5개 행만 출력해 주세요
# 코드를 입력해 주세요
df1['petal'] = df1['petal_length'] * df1['petal_width']
# 상위 5개 행 출력
df1.head(5)
sepal_length | sepal_width | petal_length | petal_width | species | sepal | petal | |
---|---|---|---|---|---|---|---|
0 | 5.10 | 3.50 | 1.40 | 0.20 | setosa | 17.85 | 0.28 |
1 | 4.90 | 3.00 | 1.40 | 0.20 | setosa | 14.70 | 0.28 |
2 | 4.70 | 3.20 | 1.30 | 0.20 | setosa | 15.04 | 0.26 |
3 | 4.60 | 3.10 | 1.50 | 0.20 | setosa | 14.26 | 0.30 |
4 | 5.00 | 3.60 | 1.40 | 0.20 | setosa | 18.00 | 0.28 |
[출력 결과]
sepal_length | sepal_width | petal_length | petal_width | species | sepal | petal | |
---|---|---|---|---|---|---|---|
0 | 5.10 | 3.50 | 1.40 | 0.20 | setosa | 17.85 | 0.28 |
1 | 4.90 | 3.00 | 1.40 | 0.20 | setosa | 14.70 | 0.28 |
2 | 4.70 | 3.20 | 1.30 | 0.20 | setosa | 15.04 | 0.26 |
3 | 4.60 | 3.10 | 1.50 | 0.20 | setosa | 14.26 | 0.30 |
4 | 5.00 | 3.60 | 1.40 | 0.20 | setosa | 18.00 | 0.28 |
petal_length
,petal_width
컬럼을 제거하세요- 상위 5개 행만 출력해 주세요
# 코드를 입력해 주세요
df1 = df1.drop(columns=['petal_length', 'petal_width'])
df1.head()
sepal_length | sepal_width | species | sepal | petal | |
---|---|---|---|---|---|
0 | 5.10 | 3.50 | setosa | 17.85 | 0.28 |
1 | 4.90 | 3.00 | setosa | 14.70 | 0.28 |
2 | 4.70 | 3.20 | setosa | 15.04 | 0.26 |
3 | 4.60 | 3.10 | setosa | 14.26 | 0.30 |
4 | 5.00 | 3.60 | setosa | 18.00 | 0.28 |
[출력 결과]
sepal_length | sepal_width | species | sepal | petal | |
---|---|---|---|---|---|
0 | 5.10 | 3.50 | setosa | 17.85 | 0.28 |
1 | 4.90 | 3.00 | setosa | 14.70 | 0.28 |
2 | 4.70 | 3.20 | setosa | 15.04 | 0.26 |
3 | 4.60 | 3.10 | setosa | 14.26 | 0.30 |
4 | 5.00 | 3.60 | setosa | 18.00 | 0.28 |
species
가 setosa인 꽃 중sepal
을 기준으로 내림차순 정렬 하세요.- 상위 10개의 행만 출력하세요
# 코드를 입력해 주세요
setosa_df = df1[df1['species'] == 'setosa'].sort_values(by='sepal', ascending=False)
setosa_df.head(10)
sepal_length | sepal_width | species | sepal | petal | |
---|---|---|---|---|---|
15 | 5.70 | 4.40 | setosa | 25.08 | 0.60 |
14 | 5.80 | 4.00 | setosa | 23.20 | 0.24 |
33 | 5.50 | 4.20 | setosa | 23.10 | 0.28 |
18 | 5.70 | 3.80 | setosa | 21.66 | 0.51 |
32 | 5.20 | 4.10 | setosa | 21.32 | 0.15 |
5 | 5.40 | 3.90 | setosa | 21.06 | 0.68 |
16 | 5.40 | 3.90 | setosa | 21.06 | 0.52 |
10 | 5.40 | 3.70 | setosa | 19.98 | 0.30 |
48 | 5.30 | 3.70 | setosa | 19.61 | 0.30 |
46 | 5.10 | 3.80 | setosa | 19.38 | 0.32 |
[출력 결과]
sepal_length | sepal_width | species | sepal | petal | |
---|---|---|---|---|---|
15 | 5.70 | 4.40 | setosa | 25.08 | 0.60 |
14 | 5.80 | 4.00 | setosa | 23.20 | 0.24 |
33 | 5.50 | 4.20 | setosa | 23.10 | 0.28 |
18 | 5.70 | 3.80 | setosa | 21.66 | 0.51 |
32 | 5.20 | 4.10 | setosa | 21.32 | 0.15 |
5 | 5.40 | 3.90 | setosa | 21.06 | 0.68 |
16 | 5.40 | 3.90 | setosa | 21.06 | 0.52 |
10 | 5.40 | 3.70 | setosa | 19.98 | 0.30 |
48 | 5.30 | 3.70 | setosa | 19.61 | 0.30 |
46 | 5.10 | 3.80 | setosa | 19.38 | 0.32 |
sepal
컬럼의 평균과 petal
컬럼의 평균의 차이를 구하세요
# 코드를 입력해 주세요
sepal_mean = df1['sepal'].mean()
petal_mean = df1['petal'].mean()
sepal_mean - petal_mean
12.028799999999997
[출력 결과]
12.028799999999997
category 타입¶
df1 = df.copy()
df1.head(2)
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False |
df1.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 survived 891 non-null int64 1 pclass 891 non-null int64 2 sex 891 non-null object 3 age 714 non-null float64 4 sibsp 891 non-null int64 5 parch 891 non-null int64 6 fare 891 non-null float64 7 embarked 889 non-null object 8 class 891 non-null category 9 who 891 non-null object 10 adult_male 891 non-null bool 11 deck 203 non-null category 12 embark_town 889 non-null object 13 alive 891 non-null object 14 alone 891 non-null bool dtypes: bool(2), category(2), float64(2), int64(4), object(5) memory usage: 80.7+ KB
category
로 변경
category
로 변경시에는 Categories가 같이 출력 됩니다.
df1['who'].astype('category').head()
0 man 1 woman 2 woman 3 woman 4 man Name: who, dtype: category Categories (3, object): ['child', 'man', 'woman']
변경사항을 적용합니다.
df1['who'] = df1['who'].astype('category')
category
타입으로 변경시 사용하는 메모리도 감소합니다.
df1.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 survived 891 non-null int64 1 pclass 891 non-null int64 2 sex 891 non-null object 3 age 714 non-null float64 4 sibsp 891 non-null int64 5 parch 891 non-null int64 6 fare 891 non-null float64 7 embarked 889 non-null object 8 class 891 non-null category 9 who 891 non-null category 10 adult_male 891 non-null bool 11 deck 203 non-null category 12 embark_town 889 non-null object 13 alive 891 non-null object 14 alone 891 non-null bool dtypes: bool(2), category(3), float64(2), int64(4), object(4) memory usage: 74.7+ KB
타입을 category
로 변환했다면 .cat으로 접근하여 category 타입이 제공하는 attribute를 사용할 수 있습니다.
카테고리 출력
df1['who'].cat.categories
Index(['child', 'man', 'woman'], dtype='object')
카테고리 이름 변경
- 변경시 원래 순서에 맞게 입력
df1['who'].cat.categories = ['아이', '남자', '여자']
df1['who'].value_counts()
남자 537 여자 271 아이 83 Name: who, dtype: int64
문자열 처리¶
from opendata import dataset
dataset.download('소상공인상권정보')
======= 다운로드 시작 ======= data/상권정보_서울.csv
0%| | 0.00/173M [00:00<?, ?B/s]
data/상권정보_경기.csv
0%| | 0.00/273M [00:00<?, ?B/s]
======= 다운로드 완료 =======
seoul = pd.read_csv('data/상권정보_서울.csv')
seoul.head()
상가업소번호 | 상호명 | 지점명 | 상권업종대분류코드 | 상권업종대분류명 | 상권업종중분류코드 | 상권업종중분류명 | 상권업종소분류코드 | 상권업종소분류명 | 표준산업분류코드 | 표준산업분류명 | 시도코드 | 시도명 | 시군구코드 | 시군구명 | 행정동코드 | 행정동명 | 법정동코드 | 법정동명 | 지번코드 | 대지구분코드 | 대지구분명 | 지번본번지 | 지번부번지 | 지번주소 | 도로명코드 | 도로명 | 건물본번지 | 건물부번지 | 건물관리번호 | 건물명 | 도로명주소 | 구우편번호 | 신우편번호 | 동정보 | 층정보 | 호정보 | 경도 | 위도 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 22767534 | BYC상신점 | 상신점 | D | 소매 | D05 | 의복의류 | D05A07 | 셔츠/내의/속옷 | NaN | NaN | 11 | 서울특별시 | 11710 | 송파구 | 1171053200 | 거여2동 | 1171011300 | 거여동 | 1171011300100360000 | 1 | 대지 | 36 | NaN | 서울특별시 송파구 거여동 36 | 117103123014 | 서울특별시 송파구 오금로 | 527 | NaN | 1171011300100360000022458 | 성암빌딩 | 서울특별시 송파구 오금로 527 | 138110 | 5768.00 | NaN | 1 | NaN | 127.15 | 37.49 |
1 | 23324279 | 제중건강원 | NaN | D | 소매 | D10 | 건강/미용식품 | D10A07 | 건강원 | G47216 | 건강보조식품 소매업 | 11 | 서울특별시 | 11560 | 영등포구 | 1156053500 | 영등포동 | 1156010600 | 영등포동5가 | 1156010600100410001 | 1 | 대지 | 41 | 1.00 | 서울특별시 영등포구 영등포동5가 41-1 | 115604154799 | 서울특별시 영등포구 영중로14길 | 11 | 17.00 | 1156010600100410002034626 | NaN | 서울특별시 영등포구 영중로14길 11-17 | 150035 | 7250.00 | NaN | 1 | NaN | 126.91 | 37.52 |
2 | 24525909 | 민속악기사 | NaN | D | 소매 | D04 | 취미/오락관련소매 | D04A09 | 악기판매 | G47593 | 악기 소매업 | 11 | 서울특별시 | 11200 | 성동구 | 1120079000 | 용답동 | 1120012200 | 용답동 | 1120012200101420011 | 1 | 대지 | 142 | 11.00 | 서울특별시 성동구 용답동 142-11 | 112004109480 | 서울특별시 성동구 용답5길 | 2 | NaN | 1120012200101420011000227 | NaN | 서울특별시 성동구 용답5길 2 | 133849 | 4803.00 | NaN | NaN | NaN | 127.05 | 37.57 |
3 | 17174119 | 쓰리에프 | NaN | Q | 음식 | Q01 | 한식 | Q01A01 | 한식/백반/한정식 | I56111 | 한식 음식점업 | 11 | 서울특별시 | 11590 | 동작구 | 1159063000 | 사당2동 | 1159010700 | 사당동 | 1159010700101390072 | 1 | 대지 | 139 | 72.00 | 서울특별시 동작구 사당동 139-72 | 115904157119 | 서울특별시 동작구 동작대로27가길 | 12 | NaN | 1159010700101390073009536 | NaN | 서울특별시 동작구 동작대로27가길 12 | 156816 | 7008.00 | NaN | NaN | NaN | 126.98 | 37.49 |
4 | 17174096 | 채움 | NaN | Q | 음식 | Q01 | 한식 | Q01A01 | 한식/백반/한정식 | I56111 | 한식 음식점업 | 11 | 서울특별시 | 11110 | 종로구 | 1111061500 | 종로1.2.3.4가동 | 1111012400 | 수송동 | 1111012400100580000 | 1 | 대지 | 58 | NaN | 서울특별시 종로구 수송동 58 | 111103100006 | 서울특별시 종로구 삼봉로 | 81 | NaN | 1111012400100580000017956 | 두산위브파빌리온 | 서울특별시 종로구 삼봉로 81 | 110858 | 3150.00 | NaN | NaN | NaN | 126.98 | 37.57 |
seoul.head().T
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
상가업소번호 | 22767534 | 23324279 | 24525909 | 17174119 | 17174096 |
상호명 | BYC상신점 | 제중건강원 | 민속악기사 | 쓰리에프 | 채움 |
지점명 | 상신점 | NaN | NaN | NaN | NaN |
상권업종대분류코드 | D | D | D | Q | Q |
상권업종대분류명 | 소매 | 소매 | 소매 | 음식 | 음식 |
상권업종중분류코드 | D05 | D10 | D04 | Q01 | Q01 |
상권업종중분류명 | 의복의류 | 건강/미용식품 | 취미/오락관련소매 | 한식 | 한식 |
상권업종소분류코드 | D05A07 | D10A07 | D04A09 | Q01A01 | Q01A01 |
상권업종소분류명 | 셔츠/내의/속옷 | 건강원 | 악기판매 | 한식/백반/한정식 | 한식/백반/한정식 |
표준산업분류코드 | NaN | G47216 | G47593 | I56111 | I56111 |
표준산업분류명 | NaN | 건강보조식품 소매업 | 악기 소매업 | 한식 음식점업 | 한식 음식점업 |
시도코드 | 11 | 11 | 11 | 11 | 11 |
시도명 | 서울특별시 | 서울특별시 | 서울특별시 | 서울특별시 | 서울특별시 |
시군구코드 | 11710 | 11560 | 11200 | 11590 | 11110 |
시군구명 | 송파구 | 영등포구 | 성동구 | 동작구 | 종로구 |
행정동코드 | 1171053200 | 1156053500 | 1120079000 | 1159063000 | 1111061500 |
행정동명 | 거여2동 | 영등포동 | 용답동 | 사당2동 | 종로1.2.3.4가동 |
법정동코드 | 1171011300 | 1156010600 | 1120012200 | 1159010700 | 1111012400 |
법정동명 | 거여동 | 영등포동5가 | 용답동 | 사당동 | 수송동 |
지번코드 | 1171011300100360000 | 1156010600100410001 | 1120012200101420011 | 1159010700101390072 | 1111012400100580000 |
대지구분코드 | 1 | 1 | 1 | 1 | 1 |
대지구분명 | 대지 | 대지 | 대지 | 대지 | 대지 |
지번본번지 | 36 | 41 | 142 | 139 | 58 |
지번부번지 | NaN | 1.00 | 11.00 | 72.00 | NaN |
지번주소 | 서울특별시 송파구 거여동 36 | 서울특별시 영등포구 영등포동5가 41-1 | 서울특별시 성동구 용답동 142-11 | 서울특별시 동작구 사당동 139-72 | 서울특별시 종로구 수송동 58 |
도로명코드 | 117103123014 | 115604154799 | 112004109480 | 115904157119 | 111103100006 |
도로명 | 서울특별시 송파구 오금로 | 서울특별시 영등포구 영중로14길 | 서울특별시 성동구 용답5길 | 서울특별시 동작구 동작대로27가길 | 서울특별시 종로구 삼봉로 |
건물본번지 | 527 | 11 | 2 | 12 | 81 |
건물부번지 | NaN | 17.00 | NaN | NaN | NaN |
건물관리번호 | 1171011300100360000022458 | 1156010600100410002034626 | 1120012200101420011000227 | 1159010700101390073009536 | 1111012400100580000017956 |
건물명 | 성암빌딩 | NaN | NaN | NaN | 두산위브파빌리온 |
도로명주소 | 서울특별시 송파구 오금로 527 | 서울특별시 영등포구 영중로14길 11-17 | 서울특별시 성동구 용답5길 2 | 서울특별시 동작구 동작대로27가길 12 | 서울특별시 종로구 삼봉로 81 |
구우편번호 | 138110 | 150035 | 133849 | 156816 | 110858 |
신우편번호 | 5768.00 | 7250.00 | 4803.00 | 7008.00 | 3150.00 |
동정보 | NaN | NaN | NaN | NaN | NaN |
층정보 | 1 | 1 | NaN | NaN | NaN |
호정보 | NaN | NaN | NaN | NaN | NaN |
경도 | 127.15 | 126.91 | 127.05 | 126.98 | 126.98 |
위도 | 37.49 | 37.52 | 37.57 | 37.49 | 37.57 |
seoul['지번주소'].head()
0 서울특별시 송파구 거여동 36 1 서울특별시 영등포구 영등포동5가 41-1 2 서울특별시 성동구 용답동 142-11 3 서울특별시 동작구 사당동 139-72 4 서울특별시 종로구 수송동 58 Name: 지번주소, dtype: object
지번주소
의 주소 문자열을 공백을 기준으로 분리하고자 하는 경우
str
의 split() 함수로 처리할 수 있습니다.- 단,
str
관련 함수 사용시str
접근자를 활용하여 문자열을 처리합니다.
seoul['지번주소'].str.split()
0 [서울특별시, 송파구, 거여동, 36] 1 [서울특별시, 영등포구, 영등포동5가, 41-1] 2 [서울특별시, 성동구, 용답동, 142-11] 3 [서울특별시, 동작구, 사당동, 139-72] 4 [서울특별시, 종로구, 수송동, 58] ... 325875 [서울특별시, 마포구, 망원동, 483-22] 325876 [서울특별시, 은평구, 녹번동, 283] 325877 [서울특별시, 은평구, 신사동, 237-95] 325878 [서울특별시, 광진구, 중곡동, 130-9] 325879 [서울특별시, 강북구, 수유동, 482-32] Name: 지번주소, Length: 325880, dtype: object
만약, 분리한 리스트 중 2번째 요소인(지역구)만 가져오고 싶은 경우 다음과 같이 처리할 수 있습니다.
- 다시
str
접근자로 조회 후 1번 index만 가져옵니다.
seoul['지번주소'].str.split().str[1]
0 송파구 1 영등포구 2 성동구 3 동작구 4 종로구 ... 325875 마포구 325876 은평구 325877 은평구 325878 광진구 325879 강북구 Name: 지번주소, Length: 325880, dtype: object
혹은 apply 함수를 활용하여 처리할 수 있습니다.
apply()
함수로 처리시에는str
접근자를 활용할 필요 없습니다.
seoul['지번주소'].apply(lambda x: x.split()[1])
0 송파구 1 영등포구 2 성동구 3 동작구 4 종로구 ... 325875 마포구 325876 은평구 325877 은평구 325878 광진구 325879 강북구 Name: 지번주소, Length: 325880, dtype: object
연습문제¶
상권업종소분류명
컬럼에는 다음과 같이 여러 업종의 명칭이 있습니다.
한식/백반/한정식
처럼 여러 업종이 / 구분자로 분리되어 있는 경우 첫 번째 값인한식
만 표기될 수 있도록 변경하세요편의점
과 같이 단일 업종만 나와있는 경우에는 그대로편의점
이라고 표기할 수 있도록 유지합니다.
seoul['상권업종소분류명'].value_counts().head(10)
한식/백반/한정식 29686 커피전문점/카페/다방 19206 여성미용실 15503 부동산중개 14100 편의점 8021 일반의류 7410 종합소매 7033 호프/맥주 6595 비만/피부관리 6228 라면김밥분식 6031 Name: 상권업종소분류명, dtype: int64
# 코드를 입력해 주세요
seoul['상권업종소분류명'] = seoul['상권업종소분류명'].apply(lambda x: x.split('/')[0])
seoul['상권업종소분류명'].value_counts().head(10)
한식 29686 커피전문점 19206 여성미용실 15503 부동산중개 14100 편의점 8021 일반의류 7410 종합소매 7033 호프 6595 비만 6228 라면김밥분식 6031 Name: 상권업종소분류명, dtype: int64
[출력 결과]
한식 29686 커피전문점 19206 여성미용실 15503 부동산중개 14100 편의점 8021 일반의류 7410 종합소매 7033 호프 6595 비만 6228 라면김밥분식 6031 Name: 상권업종소분류명, dtype: int64
datetime - 날짜, 시간¶
datetime 타입이 가지는 고유 기능¶
datetime
타입에서는 dt 접근자로 다음과 같은 날짜 속성에 쉽게 접근할 수 있습니다.
Pandas의 dt (datetime) 날짜 관련 변수는 다음과 같습니다.
- pandas.Series.dt.year: 연도
- pandas.Series.dt.month: 월
- pandas.Series.dt.day: 일
- pandas.Series.dt.hour: 시
- pandas.Series.dt.minute: 분
- pandas.Series.dt.second: 초
- pandas.Series.dt.microsecond: micro 초
- pandas.Series.dt.nanosecond: nano 초
- pandas.Series.dt.week: 주
- pandas.Series.dt.weekofyear: 연중 몇 째주
- pandas.Series.dt.dayofweek: 요일
- pandas.Series.dt.weekday: 요일 (dayofweek과 동일)
- pandas.Series.dt.dayofyear: 연중 몇 번째 날
- pandas.Series.dt.quarter: 분기
to_datetime¶
샘플용 서울시 공공자전거 데이터를 로드합니다.
# 실습용 데이터셋 다운로드
from opendata import dataset
dataset.download('서울시자전거')
======= 다운로드 시작 ======= data/seoul_bicycle.csv
0%| | 0.00/31.1M [00:00<?, ?B/s]
======= 다운로드 완료 =======
# 데이터셋 로드
df2 = pd.read_csv('data/seoul_bicycle.csv')
df2.head()
대여일자 | 대여소번호 | 대여소명 | 대여구분코드 | 성별 | 연령대코드 | 이용건수 | 운동량 | 탄소량 | 이동거리 | 이용시간 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Jan-20-2020 | 3 | 중랑센터 | 일일(회원) | M | AGE_003 | 3 | 61.82 | 0.52 | 2230.00 | 75 |
1 | Jan-20-2020 | 3 | 중랑센터 | 일일(회원) | M | AGE_004 | 1 | 39.62 | 0.28 | 1220.00 | 15 |
2 | Jan-20-2020 | 3 | 중랑센터 | 정기 | M | AGE_005 | 3 | 430.85 | 4.01 | 17270.00 | 53 |
3 | Jan-20-2020 | 5 | 상암센터 정비실 | 일일(회원) | \N | AGE_005 | 2 | 1.79 | 0.02 | 90.00 | 33 |
4 | Jan-20-2020 | 5 | 상암센터 정비실 | 정기 | F | AGE_003 | 1 | 4501.96 | 45.47 | 196010.00 | 64 |
df2.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 327231 entries, 0 to 327230 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 대여일자 327231 non-null object 1 대여소번호 327231 non-null int64 2 대여소명 327231 non-null object 3 대여구분코드 327231 non-null object 4 성별 272841 non-null object 5 연령대코드 327231 non-null object 6 이용건수 327231 non-null int64 7 운동량 327231 non-null object 8 탄소량 327231 non-null object 9 이동거리 327231 non-null float64 10 이용시간 327231 non-null int64 dtypes: float64(1), int64(3), object(7) memory usage: 27.5+ MB
대여일자 컬럼은 날짜 관련 컬럼처럼 보이나 info()
는 object로 인식하였습니다.
datetime
타입으로 변경해야 .dt 접근자를 사용할 수 있습니다.
pd.to_datetime()
: datetime type으로 변환합니다.
pd.to_datetime(df2['대여일자'])
0 2020-01-20 1 2020-01-20 2 2020-01-20 3 2020-01-20 4 2020-01-20 ... 327226 2020-05-20 327227 2020-05-20 327228 2020-05-20 327229 2020-05-20 327230 2020-05-20 Name: 대여일자, Length: 327231, dtype: datetime64[ns]
재대입하여 컬럼에 적용합니다.
df2['대여일자'] = pd.to_datetime(df2['대여일자'])
df2.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 327231 entries, 0 to 327230 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 대여일자 327231 non-null datetime64[ns] 1 대여소번호 327231 non-null int64 2 대여소명 327231 non-null object 3 대여구분코드 327231 non-null object 4 성별 272841 non-null object 5 연령대코드 327231 non-null object 6 이용건수 327231 non-null int64 7 운동량 327231 non-null object 8 탄소량 327231 non-null object 9 이동거리 327231 non-null float64 10 이용시간 327231 non-null int64 dtypes: datetime64[ns](1), float64(1), int64(3), object(6) memory usage: 27.5+ MB
적용된 후 .dt
접근자를 활용하여 datetime 속성에 접근할 수 있습니다.
df2['대여일자'].dt.year
0 2020 1 2020 2 2020 3 2020 4 2020 ... 327226 2020 327227 2020 327228 2020 327229 2020 327230 2020 Name: 대여일자, Length: 327231, dtype: int64
df2['대여일자'].dt.month
0 1 1 1 2 1 3 1 4 1 .. 327226 5 327227 5 327228 5 327229 5 327230 5 Name: 대여일자, Length: 327231, dtype: int64
df2['대여일자'].dt.day
0 20 1 20 2 20 3 20 4 20 .. 327226 20 327227 20 327228 20 327229 20 327230 20 Name: 대여일자, Length: 327231, dtype: int64
df2['대여일자'].dt.dayofweek
0 0 1 0 2 0 3 0 4 0 .. 327226 2 327227 2 327228 2 327229 2 327230 2 Name: 대여일자, Length: 327231, dtype: int64
연습문제¶
# 데이터셋 로드
df2 = pd.read_csv('data/seoul_bicycle.csv')
df2.head()
대여일자 | 대여소번호 | 대여소명 | 대여구분코드 | 성별 | 연령대코드 | 이용건수 | 운동량 | 탄소량 | 이동거리 | 이용시간 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Jan-20-2020 | 3 | 중랑센터 | 일일(회원) | M | AGE_003 | 3 | 61.82 | 0.52 | 2230.00 | 75 |
1 | Jan-20-2020 | 3 | 중랑센터 | 일일(회원) | M | AGE_004 | 1 | 39.62 | 0.28 | 1220.00 | 15 |
2 | Jan-20-2020 | 3 | 중랑센터 | 정기 | M | AGE_005 | 3 | 430.85 | 4.01 | 17270.00 | 53 |
3 | Jan-20-2020 | 5 | 상암센터 정비실 | 일일(회원) | \N | AGE_005 | 2 | 1.79 | 0.02 | 90.00 | 33 |
4 | Jan-20-2020 | 5 | 상암센터 정비실 | 정기 | F | AGE_003 | 1 | 4501.96 | 45.47 | 196010.00 | 64 |
대여일자 컬럼에서 연도, 월, 일, 요일 데이터를 추출하여 컬럼을 추가하세요.
- 상위 5개 행만 출력하세요
# 코드를 입력해 주세요
# 대여일자 컬럼을 datetime 형식으로 변환
df2['대여일자'] = pd.to_datetime(df2['대여일자'])
# 연도, 월, 일, 요일 추출하여 새로운 컬럼 추가
df2['연도'] = df2['대여일자'].dt.year
df2['월'] = df2['대여일자'].dt.month
df2['일'] = df2['대여일자'].dt.day
df2['요일'] = df2['대여일자'].dt.day_name()
df2.head()
대여일자 | 대여소번호 | 대여소명 | 대여구분코드 | 성별 | 연령대코드 | 이용건수 | 운동량 | 탄소량 | 이동거리 | 이용시간 | 연도 | 월 | 일 | 요일 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_003 | 3 | 61.82 | 0.52 | 2230.00 | 75 | 2020 | 1 | 20 | Monday |
1 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_004 | 1 | 39.62 | 0.28 | 1220.00 | 15 | 2020 | 1 | 20 | Monday |
2 | 2020-01-20 | 3 | 중랑센터 | 정기 | M | AGE_005 | 3 | 430.85 | 4.01 | 17270.00 | 53 | 2020 | 1 | 20 | Monday |
3 | 2020-01-20 | 5 | 상암센터 정비실 | 일일(회원) | \N | AGE_005 | 2 | 1.79 | 0.02 | 90.00 | 33 | 2020 | 1 | 20 | Monday |
4 | 2020-01-20 | 5 | 상암센터 정비실 | 정기 | F | AGE_003 | 1 | 4501.96 | 45.47 | 196010.00 | 64 | 2020 | 1 | 20 | Monday |
[출력 결과]
대여일자 | 대여소번호 | 대여소명 | 대여구분코드 | 성별 | 연령대코드 | 이용건수 | 운동량 | 탄소량 | 이동거리 | 이용시간 | 연도 | 월 | 일 | 요일 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_003 | 3 | 61.82 | 0.52 | 2230.00 | 75 | 2020 | 1 | 20 | 0 |
1 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_004 | 1 | 39.62 | 0.28 | 1220.00 | 15 | 2020 | 1 | 20 | 0 |
2 | 2020-01-20 | 3 | 중랑센터 | 정기 | M | AGE_005 | 3 | 430.85 | 4.01 | 17270.00 | 53 | 2020 | 1 | 20 | 0 |
3 | 2020-01-20 | 5 | 상암센터 정비실 | 일일(회원) | \N | AGE_005 | 2 | 1.79 | 0.02 | 90.00 | 33 | 2020 | 1 | 20 | 0 |
4 | 2020-01-20 | 5 | 상암센터 정비실 | 정기 | F | AGE_003 | 1 | 4501.96 | 45.47 | 196010.00 | 64 | 2020 | 1 | 20 | 0 |
pd.cut() - 구간 나누기(binning)¶
연속된 수치(continuous values)를 구간으로 나누어 카테고리화 할 때 사용합니다.
df2.head()
대여일자 | 대여소번호 | 대여소명 | 대여구분코드 | 성별 | 연령대코드 | 이용건수 | 운동량 | 탄소량 | 이동거리 | 이용시간 | 연도 | 월 | 일 | 요일 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_003 | 3 | 61.82 | 0.52 | 2230.00 | 75 | 2020 | 1 | 20 | Monday |
1 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_004 | 1 | 39.62 | 0.28 | 1220.00 | 15 | 2020 | 1 | 20 | Monday |
2 | 2020-01-20 | 3 | 중랑센터 | 정기 | M | AGE_005 | 3 | 430.85 | 4.01 | 17270.00 | 53 | 2020 | 1 | 20 | Monday |
3 | 2020-01-20 | 5 | 상암센터 정비실 | 일일(회원) | \N | AGE_005 | 2 | 1.79 | 0.02 | 90.00 | 33 | 2020 | 1 | 20 | Monday |
4 | 2020-01-20 | 5 | 상암센터 정비실 | 정기 | F | AGE_003 | 1 | 4501.96 | 45.47 | 196010.00 | 64 | 2020 | 1 | 20 | Monday |
직접 범위 설정을 해줄 수 있습니다.
right=False
로 지정시 우측 범위를 포함하지 않습니다.
bins = [0, 6000, 100000, df2['이동거리'].max()]
pd.cut(df2['이동거리'], bins, right=False)
0 [0.0, 6000.0) 1 [0.0, 6000.0) 2 [6000.0, 100000.0) 3 [0.0, 6000.0) 4 [100000.0, 56709052.94) ... 327226 [6000.0, 100000.0) 327227 [0.0, 6000.0) 327228 [0.0, 6000.0) 327229 [0.0, 6000.0) 327230 [100000.0, 56709052.94) Name: 이동거리, Length: 327231, dtype: category Categories (3, interval[float64, left]): [[0.0, 6000.0) < [6000.0, 100000.0) < [100000.0, 56709052.94)]
labels
를 지정해 줄 수 있으며, 지정한 bins의 개수보다 1 개가 적어야 합니다.
labels = ['적음', '보통', '많음']
pd.cut(df2['이동거리'], bins, labels=labels, right=False)
0 적음 1 적음 2 보통 3 적음 4 많음 .. 327226 보통 327227 적음 327228 적음 327229 적음 327230 많음 Name: 이동거리, Length: 327231, dtype: category Categories (3, object): ['적음' < '보통' < '많음']
pd.cut()
을 활용하여 쉽게 그룹을 나눌 수 있습니다.
df2.head()
대여일자 | 대여소번호 | 대여소명 | 대여구분코드 | 성별 | 연령대코드 | 이용건수 | 운동량 | 탄소량 | 이동거리 | 이용시간 | 연도 | 월 | 일 | 요일 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_003 | 3 | 61.82 | 0.52 | 2230.00 | 75 | 2020 | 1 | 20 | Monday |
1 | 2020-01-20 | 3 | 중랑센터 | 일일(회원) | M | AGE_004 | 1 | 39.62 | 0.28 | 1220.00 | 15 | 2020 | 1 | 20 | Monday |
2 | 2020-01-20 | 3 | 중랑센터 | 정기 | M | AGE_005 | 3 | 430.85 | 4.01 | 17270.00 | 53 | 2020 | 1 | 20 | Monday |
3 | 2020-01-20 | 5 | 상암센터 정비실 | 일일(회원) | \N | AGE_005 | 2 | 1.79 | 0.02 | 90.00 | 33 | 2020 | 1 | 20 | Monday |
4 | 2020-01-20 | 5 | 상암센터 정비실 | 정기 | F | AGE_003 | 1 | 4501.96 | 45.47 | 196010.00 | 64 | 2020 | 1 | 20 | Monday |
bins
옵션에 나누고자 하는 구간의 개수를 설정합니다.
df2['이동거리_cut'] = pd.cut(df2['이동거리'], bins=3)
df2['이동거리_cut'].value_counts()
(-56709.053, 18903017.647] 327216 (18903017.647, 37806035.293] 12 (37806035.293, 56709052.94] 3 Name: 이동거리_cut, dtype: int64
분포를 보니 첫 구간에 대부분의 데이터가 쏠려 있습니다. 딱봐도 올바르지 않은 방법 같아 보입니다.
pd.cut()
은 최소에서 최대 구간을 지정한 bin만큼 동일하게 분할 하기 때문에 이런 현상이 발생할 수 있습니다.
고르게 분포한 데이터라면 괜찮지만, 튀는 이상치(outlier)가 있는 경우에는 안 좋은 결과를 초래 합니다.
pd.qcut() - 동일한 갯수를 갖도록 구간 분할¶
pd.cut()
과 유사하지만, quantity 즉 데이터의 분포를 최대한 비슷하게 유지하는 구간을 분할 합니다.
df2['이동거리_qcut'] = pd.qcut(df2['이동거리'], q=3)
df2['이동거리_qcut'].value_counts()
(-0.001, 9030.0] 109095 (60470.0, 56709052.94] 109072 (9030.0, 60470.0] 109064 Name: 이동거리_qcut, dtype: int64
구간도 예쁘게 분할(균등하게 분할)이 된 것 처럼 보입니다. 하지만, 간격은 일정하지 않습니다.
qcut 또한 임의 범위를 조정할 수 있습니다.
qcut_bins = [0, 0.2, 0.8, 1]
pd.qcut(df2['이동거리'], qcut_bins)
0 (-0.001, 3570.0] 1 (-0.001, 3570.0] 2 (3570.0, 125530.0] 3 (-0.001, 3570.0] 4 (125530.0, 56709052.94] ... 327226 (3570.0, 125530.0] 327227 (-0.001, 3570.0] 327228 (-0.001, 3570.0] 327229 (-0.001, 3570.0] 327230 (125530.0, 56709052.94] Name: 이동거리, Length: 327231, dtype: category Categories (3, interval[float64, right]): [(-0.001, 3570.0] < (3570.0, 125530.0] < (125530.0, 56709052.94]]
qcut 역시 label을 지정할 수 있습니다. 마찬가지로 범위 수보다 1개 적게 설정합니다.
qcut_labels = ['적음', '보통', '많음']
pd.qcut(df2['이동거리'], qcut_bins, labels=qcut_labels).value_counts()
보통 196307 적음 65482 많음 65442 Name: 이동거리, dtype: int64
연습문제¶
sample = sns.load_dataset('titanic')
sample.head(3)
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.00 | 1 | 0 | 7.25 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.00 | 1 | 0 | 71.28 | C | First | woman | False | C | Cherbourg | yes | False |
2 | 1 | 3 | female | 26.00 | 0 | 0 | 7.92 | S | Third | woman | False | NaN | Southampton | yes | True |
age
를 다음과 같은 구간을 가지도록 나누어 주세요
- 0세 초과 ~ 15세 이하
- 15세 초과 ~ 30세 이하
- 30세 초과 ~ 45세 이하
- 45세 초과 ~ 최대값
나눈 다음 age_bin
컬럼을 생성하여 나눈 값을 대입하고 분포를 출력하세요
cut()
함수를 활용하세요
# 코드를 입력해 주세요
# 구간을 나누고 age_bin 컬럼 생성
bins = [0, 15, 30, 45, sample['age'].max()]
labels = ['0세 초과 ~ 15세 이하', '15세 초과 ~ 30세 이하', '30세 초과 ~ 45세 이하', '45세 초과 ~ 최대값']
sample['age_bin'] = pd.cut(df['age'], bins=bins, labels=labels, right=True)
sample['age_bin'].value_counts()
15세 초과 ~ 30세 이하 326 30세 초과 ~ 45세 이하 202 45세 초과 ~ 최대값 103 0세 초과 ~ 15세 이하 83 Name: age_bin, dtype: int64
[출력 결과]
(15.0, 30.0] 326 (30.0, 45.0] 202 (45.0, 80.0] 103 (0.0, 15.0] 83 Name: age_bin, dtype: int64
나이를 3개의 균등 분할을 갖도록 구간을 나누고 분포를 출력하세요
- 나이가 어린 그룹부터 차례대로 'young', 'normal', 'old' 라벨을 부여하세요
qcut()
함수를 활용하세요
# 코드를 입력해 주세요
labels = ['young', 'normal', 'old']
sample['age_bin'] = pd.qcut(sample['age'], q=3, labels=labels)
sample['age_bin'].value_counts()
young 246 old 236 normal 232 Name: age_bin, dtype: int64
[출력 결과]
young 246 old 236 normal 232 Name: age_qbin, dtype: int64
제출¶
제출을 위해 새로 로드된 아이리스 데이터셋에서 sepal
컬럼을 생성하고, sepal_length
와 sepal_width
를 곱한 값을 대입한 결과를 result_df
에 저장하세요.
- 저장할 때 상위 5개 행(
head
)이 아닌 전체 데이터를 저장합니다.
iris = sns.load_dataset('iris')
iris['sepal'] = iris['sepal_length'] * iris['sepal_width']
# 결과를 result_df에 저장
result_df = iris
result_df.head()
sepal_length | sepal_width | petal_length | petal_width | species | sepal | |
---|---|---|---|---|---|---|
0 | 5.10 | 3.50 | 1.40 | 0.20 | setosa | 17.85 |
1 | 4.90 | 3.00 | 1.40 | 0.20 | setosa | 14.70 |
2 | 4.70 | 3.20 | 1.30 | 0.20 | setosa | 15.04 |
3 | 4.60 | 3.10 | 1.50 | 0.20 | setosa | 14.26 |
4 | 5.00 | 3.60 | 1.40 | 0.20 | setosa | 18.00 |
'Biusiness Insight > Data Science' 카테고리의 다른 글
[Python] Pandas groupby, pivottable 실습 (0) | 2024.06.30 |
---|---|
[Python] Pandas 고급 전처리와 피벗테이블 (0) | 2024.06.30 |
[Python] Pandas 복제, 결측치 실습 (0) | 2024.06.30 |
[Python] Pandas 복제, 결측치 (0) | 2024.06.30 |
[Python] Pandas 통계 실습 (0) | 2024.06.30 |