오늘은 파이썬 및 데이터 파트의 마지막 내용인 데이터 시각화에 대해서 배웠다. 지금까지 그래프를 그려는 봤지만 시각화에 대해서 본질적으로 배워본 것은 처음이라 많은 것을 배운 하루였다.
sort_values()ascending : 정렬 방향 지정ignore_index : 인덱스 초기화 여부 지정apt['층'].sort_values(ascending=False)
apt.sort_values(by=['층', '거래금액'], ascending=[False, True])
| 구분 | NumPy | Pandas |
|---|---|---|
| 개수 | np.size(a=sr) | sr.count() |
| 합계 | np.sum(a=sr) | sr.sum() |
| 평균 | np.mean(a=sr) | sr.mean() |
| 중위수 | np.median(a=sr) | sr.median() |
| 분산 | np.var(a=sr) | sr.var() |
| 표준편차 | np.std(a=sr) | sr.std() |
| 최솟값 | np.min(a=sr) | sr.min() |
| 최댓값 | np.max(a=sr) | sr.max() |
주로 Pandas 함수 사용
apt['거래금액'].agg(func=['count', 'sum', 'mean', 'std'])
# count 2.208900e+05
# sum 2.233578e+06
# mean 1.011172e+01
# std 7.461396e+00
# Name: 거래금액, dtype: float64
apt['거래금액'].agg(func={'개수': 'count','합계': 'sum','평균': 'mean','표준편차': 'std'})
# 개수 2.208900e+05
# 합계 2.233578e+06
# 평균 1.011172e+01
# 표준편차 7.461396e+00
# Name: 거래금액, dtype: float64
apt.select_dtypes(include='number').agg(func=['mean', 'std'])
# 거래금액 입주년도 계약년도 계약월 계약일 전용면적 층 경과년수 세대수 주차대수
# mean 10.111720 2002.322215 2021.735869 6.221241 15.823908 75.471219 9.534578 19.413654 1065.668079 1175.280823
# std 7.461396 10.396538 1.643023 3.134888 8.666083 30.573625 6.370747 10.336370 1253.131045 1614.546846
groupby()apt.groupby(by='시군구')['거래금액'].count().sort_values(ascending=False)
cond = apt['시군구'].eq('강남구')
apt[cond].groupby(by='법정동')['거래금액'].mean().sort_values(ascending=False)
groupby() + agg()apt.groupby(by=['시군구', '계약년도'])['거래금액'].agg(func=['mean', 'std'])
pivot_table()data : 데이터프레임 지정index : 행이름에 적용할 범주형 변수명 지정columns : 열이름에 적용할 범주형 변수명 지정values : 집계 함수로 요약할 연속형 변수명 지정aggfunc : 집계 함수를 문자열 또는 numpy 함수로 지정margins : 행과 열 합계를 마지막 열, 행에 추가margins_name : 합계 이름 지정변수 및 함수가 두 개 이상이면 리스트로 지정
pd.pivot_table(
data=apt,
index='시군구',
columns='계약년도',
values='거래금액',
aggfunc=['mean', 'std'],
margins=True,
margins_name='합계'
)
nunique() , unique()nunique() : 중복을 제거한 고유값 개수 반환apt['시군구'].nunique()
# 25
unique() : 중복을 제거한 고유값 확인apt['시군구'].unique()
# array(['강남구', '강동구', '강북구', '강서구', '관악구', '광진구', '구로구', '금천구', '노원구',
# '도봉구', '동대문구', '동작구', '마포구', '서대문구', '서초구', '성동구', '성북구', '송파구',
# '양천구', '영등포구', '용산구', '은평구', '종로구', '중구', '중랑구'], dtype=object)
normalize : True 지정 시 상대도수 반환apt['시군구'].value_counts().sort_index()
# 시군구
# 강남구 12291
# 강동구 11958
# 강북구 4875
# 강서구 13610
# 관악구 6911
# 광진구 4176
# 구로구 10966
# 금천구 3976
# 노원구 19204
# 도봉구 8323
# 동대문구 9181
# 동작구 8325
# 마포구 8888
# 서대문구 7958
# 서초구 9963
# 성동구 9228
# 성북구 11995
# 송파구 14186
# 양천구 9032
# 영등포구 10486
# 용산구 4023
# 은평구 9064
# 종로구 2058
# 중구 3119
# 중랑구 7094
# Name: count, dtype: int64
cols = ['시군구', '계약년도']
apt[cols].value_counts()
# 시군구 계약년도
# 노원구 2020 8386
# 강서구 2020 5703
# 구로구 2020 4532
# 송파구 2020 4532
# 성북구 2020 4316
# ...
# 금천구 2022 270
# 강북구 2022 267
# 용산구 2022 242
# 중구 2022 193
# 종로구 2022 166
# Name: count, Length: 125, dtype: int64
apt[cols].value_counts(normalize=True) * 100
# 시군구 계약년도
# 노원구 2020 3.796460
# 강서구 2020 2.581828
# 구로구 2020 2.051700
# 송파구 2020 2.051700
# 성북구 2020 1.953914
# ...
# 금천구 2022 0.122233
# 강북구 2022 0.120875
# 용산구 2022 0.109557
# 중구 2022 0.087374
# 종로구 2022 0.075151
# Name: proportion, Length: 125, dtype: float64
sort_index() 적용apt[cols].value_counts().sort_index()
# 시군구 계약년도
# 강남구 2020 3555
# 2021 2175
# 2022 861
# 2023 2264
# 2024 3436
# ...
# 중랑구 2020 2709
# 2021 1589
# 2022 413
# 2023 868
# 2024 1515
# Name: count, Length: 125, dtype: int64
reset_index() 적용apt[cols].value_counts().sort_index().reset_index()
# 시군구 계약년도 count
# 0 강남구 2020 3555
# 1 강남구 2021 2175
# 2 강남구 2022 861
# 3 강남구 2023 2264
# 4 강남구 2024 3436
# ... ... ... ...
# 120 중랑구 2020 2709
# 121 중랑구 2021 1589
# 122 중랑구 2022 413
# 123 중랑구 2023 868
# 124 중랑구 2024 1515
# 125 rows × 3 columns
crosstab()pd.crosstab()index : 행이름에 적용할 시리즈 지정columns : 열이름에 적용할 시리즈 지정normalize : True를 지정하면 셀 값별, ‘index’를 지정하면 행별, ‘columns’를 지정하면 열별 상대도수 반환margins : 합계 추가margins_name : 합계의 이름 지정dropna : 결측값 삭제 여부(기본값 True)pd.crosstab(
index=apt['시군구'],
columns=apt['계약년도'],
normalize='index',
margins=True
).tail()
# 계약년도 2020 2021 2022 2023 2024
# 시군구
# 은평구 0.371690 0.183914 0.070609 0.151920 0.221867
# 종로구 0.344509 0.215258 0.080661 0.149174 0.210398
# 중구 0.319333 0.187881 0.061879 0.172812 0.258096
# 중랑구 0.381872 0.223992 0.058218 0.122357 0.213561
# All 0.361144 0.187138 0.052560 0.153022 0.246136
describe()apt.describe(include=[int, float]).round(2)
# 거래금액 입주년도 계약년도 계약월 계약일 전용면적 층 경과년수 세대수 주차대수
# count 220890.00 220890.00 220890.00 220890.00 220890.00 220890.00 220890.00 220890.00 220890.00 220890.00
# mean 10.11 2002.32 2021.74 6.22 15.82 75.47 9.53 19.41 1065.67 1175.28
# std 7.46 10.40 1.64 3.13 8.67 30.57 6.37 10.34 1253.13 1614.55
# min 0.62 1961.00 2020.00 1.00 1.00 10.78 -3.00 -2.00 1.00 0.00
# 25% 5.70 1996.00 2020.00 4.00 8.00 59.64 5.00 12.00 259.00 241.00
# 50% 8.30 2002.00 2021.00 6.00 16.00 79.20 9.00 20.00 668.00 654.00
# 75% 12.40 2010.00 2023.00 8.00 23.00 84.96 13.00 26.00 1372.00 1401.00
# max 220.00 2024.00 2024.00 12.00 31.00 317.36 68.00 60.00 9510.00 12602.00
apt.describe(include=object)
# 단지명 시도명 시군구 법정동 지번 재건축
# count 220890 220890 220890 220890 220890 220890
# unique 6191 1 25 332 5131 2
# top 현대 서울특별시 노원구 상계동 1013 부족
# freq 1928 220890 19204 7130 1111 183056
replace() , clip()ages = pd.Series([-1, 0, 2, 3, 15])
ages.replace(15, 5)
# 0 -1
# 1 0
# 2 2
# 3 3
# 4 5
# dtype: int64
ages.replace([-1, 0], 1)
# 0 1
# 1 1
# 2 2
# 3 3
# 4 15
# dtype: int64
ages.clip(1, 5)
# 0 1
# 1 1
# 2 2
# 3 3
# 4 5
# dtype: int64
matplotlib.pyplot.rc Property| 속성 | 별칭 | 상세 내용 |
|---|---|---|
linewidth | lw | 선의 두께를 지정 |
linestyle | ls | 선의 형태를 지정 |
color | c | 데이터 요소(점, 선, 막대 등)의 색을 지정 |
facecolor | fc | 데이터 요소의 채우기 색을 지정 |
edgecolor | ec | 데이터 요소의 테두리 색을 지정 |
markeredgewidth | mew | 점의 테두리 두께를 지정 |
antialiased | aa | 픽셀 단위로 표현된 선이나 면의 가장자리를 부드럽게 보정 |
font_list = fm.findSystemFonts(fontext='ttf')
font_path = [font for font in font_list if 'Gowun' in font]
font_path
# ['/Users/taehyunan/Library/Fonts/GowunBatang-Bold.ttf',
# '/Users/taehyunan/Library/Fonts/GowunBatang-Regular.ttf',
# '/Users/taehyunan/Library/Fonts/GowunDodum-Regular.ttf']
for font in font_path:
print(fm.FontProperties(fname=font).get_name())
# Gowun Dodum
# Gowun Batang
# Gowun Batang
plt.rc(group='font', family='Gowun Batang', size=10)
plt.rc(group='figure', figsize=(8, 4), dpi=120)
plt.rc(group='axes', unicode_minus=False)
plt.rc(group='legend', frameon=True, fc='0.9', ec='0.9')
폰트 설정 오류 시 matplotlib 캐시 파일 삭제 및 폰트 설정 json 삭제 필요
fm._load_fontmanager(try_read_cache=False)
plt.savefig('test.png', bbox_inches='tight', pad_inches=0.1)
from IPython.display import Image
Image('test.png')
os.remove('test.png')
sns.color_palette()
sns.set_palette('Set1')
dir(plt.cm)
mypal = ['lightgray', 'royalblue', 'orangered']
sns.color_palette(mypal)
sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
hue='재건축',
ec='0',
palette={
'부족': 'lightgray',
'충족': 'royalblue'
}
);
| 구분 | 이름 | 기호 | 대시 튜플 |
|---|---|---|---|
| 실선 | solid | ‘-’ | ‘’ |
| 파선 | dashed | ‘--’ | (4, 1.5) |
| 1점 쇄선 | dashdot | ‘-.’ | (3, 1, 1,5, 1) |
| 점선 | dotted | ‘:’ | (1, 1) |
| un-filled markers | 채우기와 테두리 색 일체형, color만 가능 | filled markers | 채우기와 테두리 색 별도, face, edge 다 가능 |
|---|---|---|---|
‘.’ | 1 | ‘o’ | ‘p’ |
‘,’ | 2 | ‘v’ | ‘*’ |
‘1’ | 3 | ‘^’ | ‘h’ |
‘2’ | 4 | ‘<’ | ‘H’ |
‘3’ | 5 | ‘>’ | ‘D’ |
‘4’ | 6 | ‘8’ | ‘d’ |
‘+’ | 7 | ‘s’ | ‘P’ |
‘x’ | 8 | ‘X’ | |
‘\|’ | 9 | ||
‘-’ | 10 | ||
0 | 11 |
히스토그램은 일변량 연속형 변수의 도수분포표를 시각화한 것
data : 데이터프레임 지정x : 연속형 변수명 지정binwidth : 막대 너비 지정binrange : 히스토그램 범위를 튜플로 지정(구간 제한 가능)facecolor(fc) : 채우기 색 지정edgecolor(ec) : 테두리 색 지정apt['거래금액'].agg(func=['min', 'max'])
# min 0.62
# max 220.00
# Name: 거래금액, dtype: float64
sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
facecolor='1',
edgecolor='0'
);

hue : 지정한 범주형 변수의 범주별 색을 다르게 지정sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
hue='재건축',
ec='0'
);

sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
hue='재건축',
ec='0',
palette='Set1'
);

apt['재건축'].head()
# 0 부족
# 1 부족
# 2 충족
# 3 부족
# 4 충족
# Name: 재건축, dtype: object
sort_values() 사용해서 내림차순 정렬apt1 = apt.sort_values('재건축', ascending=False)
apt1['재건축'].head()
# 140335 충족
# 98022 충족
# 98020 충족
# 174035 충족
# 98018 충족
# Name: 재건축, dtype: object
hue_order 사용sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
hue='재건축',
ec='0',
hue_order=['충족', '부족']
);

plt.title() : 제목 추가y 매개변수로 제목의 높이를 실수로 지정 가능plt.xlabel() : x 축 이름 추가plt.ylabel() : y 축 이름 추가sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
hue='재건축',
ec='0',
palette=mypal
)
plt.title('아파트 거래금액 분포', size=16, fontweight='bold', color='red')
plt.xlabel('거래금액(억)')
plt.ylabel('거래건수(건)');

kde : 커널 밀도 추정 곡선 추가color : kde 곡선의 색 지정plt.xlim() : x 축을 제한sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
fc='1',
ec='0.8',
kde=True,
color='red'
)
plt.xlim(-3, 63);

stat='density' : y축을 도수에서 밀도로 변경(기본값 : count)linewidth(lw) : 곡선의 두께 지정linestyle(ls) : 곡선의 형태 지정sns.histplot(
data=apt,
x='거래금액',
binwidth=2,
binrange=(0, 60),
fc='1',
ec='0.8',
stat='density'
)
sns.kdeplot(
data=apt,
x='거래금액',
color='red',
linewidth=1,
linestyle='--'
)
plt.xlim(-3, 63);

cond = apt['시군구'].str.contains(pat='강[남동북]구')
sub = apt.loc[cond, :]
sub.groupby('시군구')['거래금액'].agg(func=['count', 'mean', 'std'])
# count mean std
# 시군구
# 강남구 12291 20.857690 12.250572
# 강동구 11958 9.412720 4.219959
# 강북구 4875 5.881168 2.092242dd
kdeplot 사용fill : 내부 채우기sns.kdeplot(
data=sub,
x='거래금액',
hue='시군구',
palette=mypal,
fill=True
)
plt.xlim(-3, 63);

상자 그림은 연속형 변수의 분포를 한눈에 요약해서 보여주는 통계적 시각화 방법
y : 연속형 변수 지정x 매개변수에 지정하면 가로로 그려짐color : 상자의 채우기 색 지정linewidth : 모든 선의 두께 지정boxprops : 상자 관련 속성을 딕셔너리로 지정medianprops : 중위수 관련 속성을 딕셔너리로 지정sns.boxplot(
data=apt,
y='거래금액',
# color='0.8',
# linewidth=0.5
boxprops={
'facecolor': 'pink',
'edgecolor': 'red'
},
medianprops={
'color': 'green'
}
);

marker : 이상치 모양 지정markersize : 이상치 크기 지정(기본값 6)markeredgecolor : 이상치 테두리 색 지정markerfacecolor : 이상치 채우기 색 지정markeredgewidth : 이상체 테두리 선의 두께 지정(기본값 1)flierprops : 이상치 관련 속성 지정out_prop = {
'marker': '*',
'markersize': 5,
'markeredgecolor': 'red',
'markeredgewidth': 0.5
}
sns.boxplot(
data=apt,
y='거래금액',
color='0.8',
linewidth=0.5,
flierprops=out_prop
);

grp = apt.groupby('시군구')['거래금액'].median().sort_values()
grp.head()
# 시군구
# 도봉구 4.9
# 금천구 5.4
# 노원구 5.5
# 중랑구 5.7
# 강북구 6.0
# Name: 거래금액, dtype: float64
order : x축의 눈금명 순서를 지정(오름차순 정렬)plt.axhline : 가로 직선 추가plt.xticks : x축 눈금명 제어rotation : 지정 각도만큼 회전sns.boxplot(
data=apt,
x='시군구',
y='거래금액',
color='0.8',
linewidth=0.5,
flierprops=out_prop,
order=grp.index
)
plt.axhline(y=apt['거래금액'].median(), color='red', linewidth=1, linestyle='--')
plt.xticks(size=8, rotation=90)
plt.xlim(-1, 25);

오늘이 파이썬 & 데이터 분석의 마지막 수업이라 강의 자료에 있는 다른 시각화 그래프들도 따로 공부를 해서 정리를 해둬야겠다. 정말 빠르게 달려왔다. 짧은 시간 너무 많은 내용을 배워 복습을 안 하면 금방 까먹을 수도 있을 것 같으니 복습을 열심히 해서 데이터 분석부터 시각화 기술을 만족스러울 정도로 키우고 싶다.