홍동이의 성장일기
[👩💻TIL 6일차 ] 유데미 스타터스 취업 부트캠프 4기 본문
목차
[84차시]데이터의 관계파악을 위한 scatterplot
[서울시 연간 기온변화 분석 및 시각화]
[90차시]서울시 연간 평균기온,최저기온,최고기온 변화 시각화
[91차시]서울시 연간 평균기온,최고기온,최저기온 한눈에보기
[전국 지점별 기온 분석]
[80차시]그래프에 수직선, 수평선 그리기
[학습목표]
그래프 내에 수직선이나 수평선을 표시하여 그래프의 특정 부분을 강조할 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
# 그래프에 한글폰트 설정
plt.rcParams['font.family']='Malgun Gothic'
# 그래프에 마이너스 기호 깨지는 문제 해결
plt.rcParams['axes.unicode_minus'] = False
# 그리드 스타일
plt.rcParams['grid.linestyle'] = '--'
plt.rcParams['grid.alpha'] = 0.3
1. 수평선, 수직선 그리기¶
1.1 수평선 그리기¶
plt.axhline(y좌표, x축시작위치, x축끝위치)
수평선의 길이가 1이라고 했을 때 x축시작위치, x축끝위치를 지정한다.
따로 지정하지 않으면 x축 전범위에 걸쳐 그려진디ㅏ.plt.hlines(y, x축시작좌표, x축끝좌표)
plt.plot([1,2,3,4], 'ko')
plt.axhline(2,0,1, color='b', alpha=0.5, ls=':')
plt.hlines(3, 0.0, 3.0, color='darkorange', ls='-.')
plt.show()
1.2 수직선 그리기¶
axvline(x좌표, y축시작위치, y축끝위치)
수직선의 길이가 1이라고 했을 때 y축시작위치, y축끝위치를 지정한다.
따로 지정하지 않으면 y축 전범위에 걸쳐 그려진디ㅏ.vlines(x, y축시작좌표, y축끝좌표)
plt.plot([1,2,3,4], 'ko')
plt.axvline(1, 0, 0.5, ls='--', color='r')
plt.vlines(2, 1.0, 3.0, ls=':', color='g')
plt.show()
2. 예제 : 요일별 판매 테이블 수¶
2.1 데이터¶
import seaborn as sns
tips = sns.load_dataset('tips')
tips.head(3)
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
Thur = tips[tips['day'] == 'Thur']
Thur['time'].value_counts()
Lunch 61
Dinner 1
Name: time, dtype: int64
Sat = tips[tips['day'] == 'Sat']
Sat['time'].value_counts()
Dinner 87
Lunch 0
Name: time, dtype: int64
Sun = tips[tips['day'] == 'Sun']
Sun['time'].value_counts()
Dinner 76
Lunch 0
Name: time, dtype: int64
2.2 요일 별 테이블 수¶
- 요일별 데이터 수
s = tips['day'].value_counts()
s
Sat 87
Sun 76
Thur 62
Fri 19
Name: day, dtype: int64
plt.figure(figsize=(15,3))
plt.barh(s.index, s.values)
plt.xticks(range(0,91,1), rotation=90)
plt.grid(axis='x')
plt.axvline(s['Fri'], color='k')
plt.axvline(s['Thur'], color='k')
plt.axvline(s['Sun'], color='k')
plt.axvline(s['Sat'], color='k')
plt.show()
위 그래프에 따르면 주말과 목요일의 테이블 수가 많은 것을 알 수 있다.
추가분석을 통해 요일에 따른 시간대를 살펴보니 주말은 모두 저녁식사였고 목요일은 점심 식사가 이루어지는 것을 알 수 있었다. 해당 식당은 목요일 점심과 주말 저녁 장사에 집중해야함을 확인했다.
[81차시]그래프에 설명적기
[학습목표]
그래프의 특정 위치에 설명을 추가할 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
# 그래프에 한글폰트 설정
plt.rcParams['font.family']='Malgun Gothic'
# 그래프에 마이너스 기호 깨지는 문제 해결
plt.rcParams['axes.unicode_minus'] = False
1. 텍스트 추가하기¶
- plt.text(x좌표, y좌표, 텍스트)
- rotation=회전각도
- ha : horizontal alignment(수평 정렬 옵션)
- va : vertical alignment(수직 정렬 옵션)
- 텍스트 상자
bbox = {'boxstyle':상자스타일, 'fc':facecolor,'ec':edgecolor,...}
boxstyle : 'round'/'square'
plt.plot([1,2,3,4], 'ko')
#세번째 좌표에 설명 추가
plt.text(2.1, 3, '(x:2, y:3)', ha='left', va='bottom', fontsize=12, rotation=45
, bbox={'boxstyle':'round', 'fc':'skyblue', 'ec':'b', 'alpha':0.3})
plt.axhline(3, ls=':', alpha=0.5, lw=0.5) #수평선
plt.axvline(2, ls=':', alpha=0.5, lw=0.5) #수직선
plt.plot(2,3,'ro') #마커 색상 변경
plt.show()
2. 화살표와 텍스트 추가하기¶
plt.annotate('텍스트',xy=(화살표x,화살표y), xytext=(텍스트x,텍스트y), arrowprops=화살표속성(딕셔너리))
- 화살표 속성
width
화살표 몸의 너비headwidth
화살표 머리의 너비headlength
화살표 머리의 길이shrink
화살표의 전체 길이
plt.plot([1,2,3,4], 'ko')
plt.axhline(2, color='orange', lw=0.5, alpha=0.5, ls='--') #수평선
plt.axvline(1, color='orange', lw=0.5, alpha=0.5, ls='--') #수직선
plt.plot(1,2,'ro') #마커 색상 변경
#텍스트와 화살표 추가
plt.annotate('(x:1,y:2)', xy=(1,2), xytext=(1.5,2.5)
, arrowprops={'width':1, 'headwidth':10, 'headlength':10, 'shrink':0.1, 'fc':'r'}
, fontsize=12, color='r')
plt.show()
[82차시] 2중y축 표시하기
[학습목표]
2중 y축을 표시하여 2가지 유형의 데이터를 한번에 표현할 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.family']='Malgun Gothic'
plt.rcParams['axes.unicode_minus']=False
plt.rcParams['font.size'] = 12
1. 샘플데이터¶
- 어떤 학생의 나이에 따른 키와 몸무게의 변화
age = [13,14,15,16,17]
height = [160,165,170,173,177]
weight = [80,85,83,78,73]
2. 두가지 정보를 하나의 그래프에 그리기¶
- 축을 분리하기 위해 객체지향으로 그린다.
- fig, ax = plt.subplots()
2.1 2중 y축 만들기¶
- x축을 공유하는 새로운 axes객체를 만든다.
axes객체.twinx()
2.2 축 레이블 표시하기¶
axes객체.set_xlabel(x레이블)
axes객체.set_ylabel(y레이블)
2.3 y축 범위 지정¶
- axes객체.set_ylim(y축눈금범위)
2.4 y축 눈금¶
- axes객체.set_yticks(y축눈금)
- axes객체.tick_params(...)
2.5 범례 표시¶
- axes객체별로 legend메소드 호출
2.6 그리드 표시¶
- axes객체.grid()
fig, ax1 = plt.subplots()
#막대그래프
ax1.bar(age, height, color='skyblue', width=0.5, ec='lightgray', label='height')
#선그래프
ax2 = ax1.twinx()
ax2.plot(age, weight, color='darkred', marker='o', ls='-.', label='weight')
#축 레이블 표시
ax1.set_xlabel('나이')
ax1.set_ylabel('키(cm)')
ax2.set_ylabel('몸무게(kg)')
#y축 범위 지정
ax1.set_ylim(150,180)
ax2.set_ylim(60,90)
#y축 눈금에 데이터만 표시
ax1.set_yticks(height)
ax2.set_yticks(weight)
#틱 색상 변경
ax1.tick_params(axis='y', colors='skyblue')
ax2.tick_params(axis='y', colors='darkred')
#범례 표시
ax1.legend()
ax2.legend()
#그리드 표시
ax1.grid(axis='y', ls='--', color='skyblue')
ax2.grid(axis='y', ls='--', color='pink')
plt.show()
[83차시]seaborn-막대그래프
[학습목표]
seaborn으로 막대그래프를 그릴 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
#seaborn은 matplotlib을 기반으로 만들어져있기 때문에 둘 다 import 해주어야 함
plt.rcParams['font.family']='Malgun Gothic'
plt.rcParams['axes.unicode_minus']=False
1. 샘플데이터¶
tips = sns.load_dataset('tips')
tips.head()
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
tips.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 244 entries, 0 to 243
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 total_bill 244 non-null float64
1 tip 244 non-null float64
2 sex 244 non-null category
3 smoker 244 non-null category
4 day 244 non-null category
5 time 244 non-null category
6 size 244 non-null int64
dtypes: category(4), float64(2), int64(1)
memory usage: 7.4 KB
2. 요일별 팁 평균¶
2.1 matplotlib으로 시각화¶
2.1.1 데이터 가공¶
- 요일별 팁 평균 계산
- 그룹핑 : 데이터프레임.groupby(그룹기준컬럼)[통계적용컬럼].통계함수
#요일로 그룹핑하여 팁의 평균을 구하기
day_tip_mean = tips.groupby('day')['tip'].mean()
day_tip_mean
day
Thur 2.771452
Fri 2.734737
Sat 2.993103
Sun 3.255132
Name: tip, dtype: float64
2.1.2 데이터 시각화¶
- plt.bar(x,y)
#막대그래프
plt.bar(day_tip_mean.index, day_tip_mean)
#레이블 지정
plt.xlabel('day')
plt.ylabel('tip')
plt.title('요일별 팁 평균', size=15)
plt.show()
2.2 seaborn으로 그리기¶
- `sns.barplot(data=데이터프레임명, x=x축컬럼, y=y축컬럼)`
- x축데이터로 그룹핑한 y축데이터의 평균값을 계산하여 그래프를 그려준다.
- 신뢰구간(CI:Confidence Interval)을 함께 표시
sns.barplot(data=tips, x='day', y='tip', ci=None)
plt.title('요일별 팁 평균', size=15)
plt.show()
#matplotlib과의 차이점: 자동으로 그룹핑 및 평균값 계산,
#막대별로 색이 다름, 신뢰구간이 표시됨, 레이블 자동 지정
3. 요일별 팁 합계¶
3.1 matplotlib으로 그리기¶
day_tip_sum = tips.groupby('day')['tip'].sum()
day_tip_sum
day
Thur 171.83
Fri 51.96
Sat 260.40
Sun 247.39
Name: tip, dtype: float64
plt.bar(day_tip_sum.index, day_tip_sum)
plt.xlabel('day')
plt.ylabel('tip')
plt.title('요일별 팁 합계', size=15)
plt.show()
3.2 seaborn으로 그리기¶
- estimator = 통계함수
4. 요일별 팁 합계를 흡연여부로 비교¶
- hue : y를 그룹핑할 컬럼
- hue 색상 변경 : palette = 구분:색상 딕셔너리
- pyplot의 메소드로 그리드 추가
sns.barplot(data=tips, x='day', y='tip', ci=None, estimator=sum, hue='smoker'
, palette ={'Yes':'gray', 'No':'skyblue'})
plt.title('요일별 팁 합계', size=15)
plt.grid(axis='y', ls=':')
plt.show()
[84차시] 데이터의 관계파악을 위한 scatterplot
[학습목표]
seaborn으로 산점도를 그릴 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.family']='Malgun Gothic'
plt.rcParams['axes.unicode_minus']='False'
1. 샘플데이터¶
tips = sns.load_dataset('tips')
tips.head()
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
2. total_bill과 tip의 관계¶
2.1 멧플롯립으로 그리기¶
plt.scatter(x,y)
plt.scatter(tips['total_bill'], tips['tip'])
plt.show()
2.2 요일 구분¶
- total_bill에 따른 tip의 분포 - 색상으로 요일 표시
'Sun':'red'
'Sat':'blue'
'Thur':'green'
'Fri':'yello'
tips['day'].unique()
['Sun', 'Sat', 'Thur', 'Fri']
Categories (4, object): ['Thur', 'Fri', 'Sat', 'Sun']
2.2.1 요일별 서브셋 만들기¶
tips_Sun = tips[tips['day']=='Sun']
tips_Sat = tips[tips['day']=='Sat']
tips_Fri = tips[tips['day']=='Fri']
tips_Thur = tips[tips['day']=='Thur']
2.2.2 시각화하기¶
plt.scatter(tips_Sun['total_bill'], tips_Sun['tip'], label='Sun', s = tips_Sun['size']*30, alpha=0.5)
plt.scatter(tips_Sat['total_bill'], tips_Sat['tip'], label='Sat', s = tips_Sat['size']*30, alpha=0.5)
plt.scatter(tips_Fri['total_bill'], tips_Fri['tip'], label='Fri', s = tips_Fri['size']*30, alpha=0.5)
plt.scatter(tips_Thur['total_bill'], tips_Thur['tip'], label='Thur', s = tips_Thur['size']*30, alpha=0.5)
#요일별로 색깔이 다르게 나타남
plt.legend()
plt.xlabel('total_bill')
plt.ylabel('tip')
plt.show()
2.3 seaborn으로 그리기¶
- `sns.scatterplot(data=데이터프레임, x=x축컬럼, y=y축컬럼)`
sns.scatterplot(data=tips, x='total_bill', y='tip', hue='day', size='size', alpha=0.5)
plt.show()
[85차시]데이터의 추세를 표현하는 lineplot
[학습목표]
Seaborn으로 선그래프를 그릴 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.family']='Malgun Gothic'
plt.rcParams['axes.unicode_minus']=False
1. 샘플데이터¶
flights = sns.load_dataset('flights')
flights.head()
year | month | passengers | |
---|---|---|---|
0 | 1949 | Jan | 112 |
1 | 1949 | Feb | 118 |
2 | 1949 | Mar | 132 |
3 | 1949 | Apr | 129 |
4 | 1949 | May | 121 |
💡연도별/월별 승객수를 나타내는 데이터이다.
flights.tail()
year | month | passengers | |
---|---|---|---|
139 | 1960 | Aug | 606 |
140 | 1960 | Sep | 508 |
141 | 1960 | Oct | 461 |
142 | 1960 | Nov | 390 |
143 | 1960 | Dec | 432 |
flights.shape
(144, 3)
# 연도별 데이터 수
flights['year'].value_counts()
1949 12
1950 12
1951 12
1952 12
1953 12
1954 12
1955 12
1956 12
1957 12
1958 12
1959 12
1960 12
Name: year, dtype: int64
# 월별 데이터 수
flights['month'].value_counts()
Jan 12
Feb 12
Mar 12
Apr 12
May 12
Jun 12
Jul 12
Aug 12
Sep 12
Oct 12
Nov 12
Dec 12
Name: month, dtype: int64
2. 연도별 승객수의 변화¶
2.1 matplotlib으로 시각화¶
- plt.plot(x,y)
2.1.1 데이터 가공¶
flights_year = flights.groupby('year')['passengers'].sum()
flights_year
year
1949 1520
1950 1676
1951 2042
1952 2364
1953 2700
1954 2867
1955 3408
1956 3939
1957 4421
1958 4572
1959 5140
1960 5714
Name: passengers, dtype: int64
2.1.2 시각화¶
plt.plot(flights_year, 'ro--')
plt.xlabel('year')
plt.ylabel('passengers')
plt.show()
2.2 seaborn¶
sns.lineplot(data=데이터프레임, x=x축컬럼, y=y축컬럼, estimator=통계함수)
estimator를 생략하면 평균으로 통계를 적용함
- 전체 데이터로 차트를 그리면 신뢰구간 표시
sns.lineplot(data=flights, x='year', y='passengers', ci=None, estimator=sum, color='r', marker='p', ls=':')
plt.show()
3. 연도-월별 승객수의 변화¶
3.1 matplotlib으로 시각화¶
3.1.1 데이터 가공¶
flights_pivot = flights.pivot(index='year', columns='month', values='passengers')
flights_pivot
month | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec |
---|---|---|---|---|---|---|---|---|---|---|---|---|
year | ||||||||||||
1949 | 112 | 118 | 132 | 129 | 121 | 135 | 148 | 148 | 136 | 119 | 104 | 118 |
1950 | 115 | 126 | 141 | 135 | 125 | 149 | 170 | 170 | 158 | 133 | 114 | 140 |
1951 | 145 | 150 | 178 | 163 | 172 | 178 | 199 | 199 | 184 | 162 | 146 | 166 |
1952 | 171 | 180 | 193 | 181 | 183 | 218 | 230 | 242 | 209 | 191 | 172 | 194 |
1953 | 196 | 196 | 236 | 235 | 229 | 243 | 264 | 272 | 237 | 211 | 180 | 201 |
1954 | 204 | 188 | 235 | 227 | 234 | 264 | 302 | 293 | 259 | 229 | 203 | 229 |
1955 | 242 | 233 | 267 | 269 | 270 | 315 | 364 | 347 | 312 | 274 | 237 | 278 |
1956 | 284 | 277 | 317 | 313 | 318 | 374 | 413 | 405 | 355 | 306 | 271 | 306 |
1957 | 315 | 301 | 356 | 348 | 355 | 422 | 465 | 467 | 404 | 347 | 305 | 336 |
1958 | 340 | 318 | 362 | 348 | 363 | 435 | 491 | 505 | 404 | 359 | 310 | 337 |
1959 | 360 | 342 | 406 | 396 | 420 | 472 | 548 | 559 | 463 | 407 | 362 | 405 |
1960 | 417 | 391 | 419 | 461 | 472 | 535 | 622 | 606 | 508 | 461 | 390 | 432 |
💡각 연도별 데이터를 행으로 불러올 수 있게 되었다.
3.1.2 시각화¶
for i in range(12):
plt.plot(flights_pivot.iloc[i], label=flights_pivot.index[i])
plt.legend()
plt.show()
💡매년 7-8월에 승객수가 가장 많다.
3.2 seaborn으로 시각화¶
sns.lineplot(data=flights, x='month', y='passengers', ci=None, hue='year')
<AxesSubplot:xlabel='month', ylabel='passengers'>
💡seaborn으로 matplotlib에 비해 간단하게 시각화가 가능하다.
[86차시]데이터의 분포를 나타내는 여러가지 그래프
[학습목표]
seaborn으로 데이터의 분포를 나타내는 여러가지 그래프를 그릴 수 있다.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.family']='Malgun Gothic'
plt.rcParams['axes.unicode_minus']=False
1. 카운트플롯¶
- 데이터를 그룹핑하여 갯수를 카운트하여 시각화
sns.countplot(data=데이터프레임, x=컬럼)
titanic = sns.load_dataset('titanic')
titanic.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 1 | 0 | 7.2500 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.0 | 1 | 0 | 71.2833 | C | First | woman | False | C | Cherbourg | yes | False |
2 | 1 | 3 | female | 26.0 | 0 | 0 | 7.9250 | S | Third | woman | False | NaN | Southampton | yes | True |
3 | 1 | 1 | female | 35.0 | 1 | 0 | 53.1000 | S | First | woman | False | C | Southampton | yes | False |
4 | 0 | 3 | male | 35.0 | 0 | 0 | 8.0500 | S | Third | man | True | NaN | Southampton | no | True |
# 연령별 승선인원 카운트하여 시각화
plt.figure(figsize=(15, 4))
sns.countplot(data=titanic, x='age')
plt.xticks(rotation=90)
plt.grid(axis='y')
plt.show()
💡24세가 가장 많이 탑승한 것을 알 수 있다.
💡소수점으로 되어있는 이상한 나이가 존재한다.
# 1. 남자/여자/어린이 승선인원 시각화
#sns.countplot(data=titanic, x='who')
# 2. 남자/여자/어린이 별 생존여부
sns.countplot(data=titanic, x='who', hue='alive')
plt.show()
💡남성 탑승객의 수가 많다.
💡남성 탑승객의 대부분은 생존하지 못했다.
2. 러그플롯¶
sns.rugplot(data=데이터프레임, x=컬럼)
데이터의 위치를 보여준다.
sns.rugplot(data=titanic, x='age', hue='alive')
plt.show()
3. 히스토그램¶
sns.displot(data=데이터프레임, x=컬럼)
데이터의 분포를 알려준다.
iris = sns.load_dataset('iris')
iris.head(1)
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
sns.displot(data=iris, x='petal_length', bins=20, rug=True, hue='species', kde=True)
plt.show()
sns.displot(data=iris, x='petal_length', rug=True, hue='species', kind='kde')
plt.show()
💡막대그래프없이 곡선으로만 분포를 확인할 수 있다.
4. 상자수염그래프, 바이올린플롯, 스트립플롯, 스웜플롯¶
- sns.boxplot(data=데이터프레임)
- sns.violinplot(data=데이터프레임)
- sns.stripplot(data=데이터프레임)
- sns.swarmplot(data=데이터프레임)
plt.figure(figsize=(12,8))
plt.subplot(221)
sns.boxplot(data=iris)
plt.subplot(222)
sns.violinplot(data=iris)
plt.subplot(223)
sns.stripplot(data=iris)
plt.subplot(224)
sns.swarmplot(data=iris, s=2)
plt.show()
plt.figure(figsize=(12,8))
plt.subplot(221)
# 박스플롯
sns.boxplot(data=iris, x='species', y='sepal_length')
plt.subplot(222)
# 바이올린플롯
sns.violinplot(data=iris, x='species', y='sepal_length')
plt.subplot(223)
# 스트립플롯
sns.stripplot(data=iris, x='species', y='sepal_length')
plt.subplot(224)
# 스웜플롯
sns.swarmplot(data=iris, x='species', y='sepal_length', s=2)
plt.show()
💡품종별 sepal_length을 확인할 수 있다.
➕) 러그 플롯은 처음 들어봤는데 무슨 용도인지 잘 이해가 가지 않아서 조금 더 알아보았다.
러그 플롯(rug plot)이란, xy 평면에서 x축 방향, y축 방향 두 개의 1차원 주변 분포를 나타내어 2차원 도표를 보완하도록 설계된 컴팩트한 시각화 방법입니다. 러그 플롯은 개별 사례를 표시하므로 작은 규모의 데이터 세트에 적합합니다.
[R] ggplot(), geom_rug() : 러그 플롯(rug plot) 그리기, 그래프에 두 변수의 marginal distribution 시각화하기
주변 분포(marginal distribution) 확률 변수들의 부분 집합의 주변 분포란, 그 부분 집합에 속한 확률 변...
blog.naver.com
[87차시]전국 기온 데이터 수집
csv파일 다운로드 후 바로 파일명을 변경해주는 것이 좋다.
[88차시]전국 기온 데이터 확인
[89차시]서울시 연간 기온변화 분석 및 시각화
[90차시]서울시 연간 평균기온,최저기온,최고기온 변화 시각화
[91차시]서울시 연간 평균기온,최고기온,최저기온 한눈에보기
[학습목표]
기상자료개방포털에서 데이터를 수집하여 전처리하고, 서울시 연간 기온 변화를 분석하고 시각화할 수 있다.
1. 전국 기온 데이터 수집¶
- 기상자료개방포털
https://data.kma.go.kr - 기상자료개방포털 > 데이터 > 기상관측 > 지상 > 종관기상관측(ASOS)
https://data.kma.go.kr/data/grnd/selectAsosRltmList.do?pgmNo=36
회원가입/로그인 필요
[ 자료형태 ] 일자료
[ 지점 ] 전체
[ 자료 ] 기온>최저,최고,평균
[ 기간 ] 1911~2020 (10년단위로 나누어 다운로드)
2. 전국 기온 데이터 확인¶
- 데이터프레임 생성하고 데이터 살펴보기
import pandas as pd
import matplotlib.pyplot as plt
# 그래프에 한글 설정
plt.rcParams['font.family']='Malgun Gothic'
# 그래프에 마이너스 기호 깨지는 문제 해결
plt.rcParams['axes.unicode_minus'] = False
2.1 데이터프레임 생성¶
- 데이터 파일(csv)을 data폴더에 업로드한다.
- pd.read_csv(파일경로, encoding ='cp949')
df_1911 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1911-1920 일별 기온.csv', encoding='cp949')
df_1921 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1921-1930 일별 기온.csv', encoding='cp949')
df_1931 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1931-1940 일별 기온.csv', encoding='cp949')
df_1941 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1941-1950 일별 기온.csv', encoding='cp949')
df_1951 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1951-1960 일별 기온.csv', encoding='cp949')
df_1961 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1961-1970 일별 기온.csv', encoding='cp949')
df_1971 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1971-1980 일별 기온.csv', encoding='cp949')
df_1981 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1981-1990 일별 기온.csv', encoding='cp949')
df_1991 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/1991-2000 일별 기온.csv', encoding='cp949')
df_2001 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/2001-2010 일별 기온.csv', encoding='cp949')
df_2011 = pd.read_csv('C:/스타터스 교육생공유용/파이썬 교재 및 실습자료/파이썬 데이터 시각화 데이터/data/2011-2020 일별 기온.csv', encoding='cp949')
2.2 데이터프레임 연결하기¶
pd.concat(데이터프레임리스트, axis=0)
: 행 방향으로 연결(default)pd.concat(데이터프레임리스트, axis=1)
: 열 방향으로 연결ignore_index=True
: 인덱스 제지정 [df_1911,df_1921,df_1931,df_1941,df_1951,df_1961,df_1971,df_1981,df_1991,df_2001,df_2011]
df = pd.concat([df_1911,df_1921,df_1931,df_1941,df_1951,df_1961,df_1971,df_1981,df_1991,df_2001,df_2011],
ignore_index = True)
💡인덱스가 중복되어있다.
2.3 데이터타입 확인/변경¶
2.3.1 데이터타입 확인¶
데이터프레임.dtypes
# 데이터타입 확인
df.dtypes
지점 int64
지점명 object
일시 object
평균기온(°C) float64
최저기온(°C) float64
최고기온(°C) float64
dtype: object
2.3.2 데이터타입 변경¶
pd.to_datetime(컬럼)
: datetime형으로 변경
# '일시' 컬럼을 datetime형으로 변경
df['일시'] = pd.to_datetime(df['일시'])
# 변경 확인
df.dtypes
지점 int64
지점명 object
일시 datetime64[ns]
평균기온(°C) float64
최저기온(°C) float64
최고기온(°C) float64
dtype: object
2.4 데이터 크기 확인¶
데이터프레임.shape
df.shape
(1596835, 6)
2.5 데이터 정보 확인¶
데이터프레임.info()
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1596835 entries, 0 to 1596834
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 지점 1596835 non-null int64
1 지점명 1596835 non-null object
2 일시 1596835 non-null datetime64[ns]
3 평균기온(°C) 1594136 non-null float64
4 최저기온(°C) 1596638 non-null float64
5 최고기온(°C) 1596667 non-null float64
dtypes: datetime64[ns](1), float64(3), int64(1), object(1)
memory usage: 73.1+ MB
💡RangeIndex: 0부터 1씩 증가하는 인덱스
2.6 데이터 내용 확인¶
2.6.1 지점명, 지점명의 개수 확인¶
- 컬럼.unique() : 컬럼의 중복을 배제한 값 목록
- 컬럼.nunique() : 컬럼의 중복을 배제한 값 개수
# 지점명 확인
df['지점명'].unique()
array(['강릉', '서울', '인천', '대구', '전주', '부산', '목포', '제주', '울릉도', '추풍령', '광주',
'포항', '울산', '여수', '속초', '춘천', '수원', '서산', '청주', '대전', '군산', '통영',
'서귀포', '진주', '임실', '정읍', '대관령', '원주', '충주', '울진', '안동', '완도', '성산',
'강화', '양평', '이천', '인제', '홍천', '삼척', '제천', '보은', '천안', '보령', '부여',
'금산', '부안', '남원', '고창군', '주암', '장흥', '해남', '고흥', '성산포', '영주', '문경',
'영덕', '의성', '구미', '영천', '거창', '합천', '밀양', '산청', '거제', '남해', '철원',
'관악산', '창원', '고산', '태백', '장수', '봉화', '동두천', '백령도', '동해', '영월',
'무안', '흑산도', '파주', '북강릉', '상주', '고창', '진도(첨찰산)', '정선군', '영광군',
'김해시', '순창군', '북창원', '양산시', '보성군', '강진군', '의령군', '함양군', '청송군',
'경주시', '북춘천', '순천', '대구(기)', '홍성', '세종', '광양시', '진도군'],
dtype=object)
# 지점명 개수 확인
df['지점명'].nunique()
102
2.6.2 연도의 개수 확인¶
- datetime에서 연도, 월, 일 가져오기
컬럼.dt.year
컬럼.dt.month
컬럼.dt.day
# 연도 개수 확인
df['일시'].dt.year.nunique()
110
2.6.3 연도별 데이터 개수 확인¶
df['일시'].dt.year.value_counts()
2020 34767
2019 34738
2018 34673
2017 34668
2016 34496
...
1917 2190
1915 2190
1914 2190
1913 2190
1911 1836
Name: 일시, Length: 110, dtype: int64
💡과거에는 데이터가 많이 수집되어있지 않다.
2.6.4 지점별 데이터 개수 확인¶
df['지점명'].value_counts()
대구 40148
부산 40148
목포 40148
인천 39660
강릉 39479
...
진도군 2423
홍성 1885
북춘천 1553
대구(기) 619
세종 581
Name: 지점명, Length: 102, dtype: int64
서울시 기온 데이터 추출 및 확인¶
서울시 데이터만 추출하여 서브셋 생성¶
- 조건으로 데이터를 추출하여 서브셋을 만들 때, copy본으로 만드는 것을 권장. :
.copy()
df_seoul = df[df['지점명']=='서울'].copy()
df_seoul
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) | |
---|---|---|---|---|---|---|
3299 | 108 | 서울 | 1911-01-01 | -10.1 | -14.2 | -6.5 |
3300 | 108 | 서울 | 1911-01-02 | -12.5 | -19.7 | -5.9 |
3301 | 108 | 서울 | 1911-01-03 | -4.3 | -10.2 | -1.4 |
3302 | 108 | 서울 | 1911-01-04 | 0.8 | -2.6 | 2.2 |
3303 | 108 | 서울 | 1911-01-05 | -3.9 | -8.7 | 1.7 |
... | ... | ... | ... | ... | ... | ... |
1295576 | 108 | 서울 | 2020-12-27 | 5.8 | 1.4 | 10.0 |
1295577 | 108 | 서울 | 2020-12-28 | 6.7 | 4.2 | 11.4 |
1295578 | 108 | 서울 | 2020-12-29 | 0.1 | -6.2 | 4.3 |
1295579 | 108 | 서울 | 2020-12-30 | -10.9 | -12.9 | -6.2 |
1295580 | 108 | 서울 | 2020-12-31 | -8.9 | -12.9 | -5.0 |
38961 rows × 6 columns
결측치 분석¶
데이터프레임.isnull().sum()
# 결측치 확인
df_seoul.isnull().sum()
지점 0
지점명 0
일시 0
평균기온(°C) 0
최저기온(°C) 2
최고기온(°C) 3
dtype: int64
# 결측치가 있는 데이터 보기
df_seoul[(df_seoul['최저기온(°C)'].isnull()) | (df_seoul['최고기온(°C)'].isnull())]
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) | |
---|---|---|---|---|---|---|
181051 | 108 | 서울 | 1967-02-19 | -1.7 | NaN | NaN |
254079 | 108 | 서울 | 1973-10-16 | 12.3 | NaN | NaN |
1294404 | 108 | 서울 | 2017-10-12 | 11.4 | 8.8 | NaN |
💡조건을 두가지 이상 적을 때는 각각의 조건에 소괄호를 해주어야 한다.
결측치 제거¶
데이터프레임.dropna()
: 결측치가 포함된 행을 모두 제거
# 결측치 제거
df_seoul = df_seoul.dropna()
💡3개의 결측치가 제거되었다.
# 결측치 확인
df_seoul.isnull().sum()
지점 0
지점명 0
일시 0
평균기온(°C) 0
최저기온(°C) 0
최고기온(°C) 0
dtype: int64
# 데이터프레임 크기
df.shape
(1596835, 6)
연도별 데이터 개수 확인¶
# 연도별 데이터 개수 확인
df_seoul['일시'].dt.year.value_counts()
2020 366
1964 366
1992 366
1988 366
1944 366
...
1973 364
1967 364
1931 335
1950 243
1953 31
Name: 일시, Length: 108, dtype: int64
💡1953년은 한국전쟁시기이기 때문에 데이터가 적은 것으로 추측할 수 있다.
💡2개의 연도 데이터가 없다.
시각화로 데이터 확인¶
- 최저기온
- 평균기온
- 최고기온
plt.plot(df_seoul['일시'], df_seoul['평균기온(°C)'])
plt.plot(df_seoul['일시'], df_seoul['최저기온(°C)'])
plt.plot(df_seoul['일시'], df_seoul['최고기온(°C)'])
plt.show()
💡1950년대 초반의 데이터가 비어있다.
# 1951년 데이터 추출
df_seoul[df_seoul['일시'].dt.year == 1951]
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) |
---|
# 1952년 데이터 추출
df_seoul[df_seoul['일시'].dt.year == 1952]
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) |
---|
💡1951, 1952년의 데이터가 없는 것을 확인할 수 있다.
서울시 연간 평균기온, 최저기온, 최고기온 변화 시각화¶
서울시 연간 평균기온 변화¶
연간 평균기온 추출¶
연간 일 평균기온의 평균
연도로 그룹화하여 연도별 평균기온 산출
df_seoul_mean = df_seoul.groupby(df_seoul['일시'].dt.year)['평균기온(°C)'].mean()
df_seoul_mean
일시
1911 10.654795
1912 10.123770
1913 10.086027
1914 12.029041
1915 10.898356
...
2016 13.592896
2017 13.077747
2018 13.002466
2019 13.598904
2020 13.271858
Name: 평균기온(°C), Length: 108, dtype: float64
# 시각화하여 데이터 확인
plt.figure(figsize=(15,5))
plt.plot(df_seoul_mean, '.')
plt.xticks(range(1911,2021,2), rotation=90)
plt.grid(ls=':')
plt.show()
💡1950년과 1953년에 평균기온에 이상치가 있다는 것을 확인하였다.
이상치 제거¶
df_seoul_mean.drop(index=[1950, 1953], inplace=True)
시각화¶
plt.plot(df_seoul_mean, 'g.-')
plt.title('서울시 연 평균기온의 변화', size=15)
plt.show()
💡서울시 연 평균기온은 점점 상승하고 있다는 것을 알 수 있다.
서울시 연간 최저기온 변화¶
서울시 연간 최저기온 추출¶
연간 일 최저기온의 최저
연도로 그룹핑하여 최저기온의 최소값 추출
df_seoul_min = df_seoul.groupby(df_seoul['일시'].dt.year)['최저기온(°C)'].min()
df_seoul_min
일시
1911 -21.5
1912 -18.6
1913 -19.6
1914 -14.0
1915 -21.3
...
2016 -18.0
2017 -12.6
2018 -17.8
2019 -10.9
2020 -12.9
Name: 최저기온(°C), Length: 108, dtype: float64
시각화¶
plt.plot(df_seoul_min, 'b.-')
plt.title('서울시 연 최저기온의 변화', size=15)
plt.show()
💡서울시의 연 최저기온 또한 상승하고 있는 추세임을 알 수 있다.
서울시 연간 최고기온 변화¶
서울시 연간 최고기온 추출¶
연간 최고기온의 최고
연도로 그룹핑하여 최고기온의 최대값 추출
df_seoul_max = df_seoul.groupby(df_seoul['일시'].dt.year)['최고기온(°C)'].max()
df_seoul_max
일시
1911 34.5
1912 34.0
1913 31.7
1914 35.6
1915 34.8
...
2016 36.6
2017 35.4
2018 39.6
2019 36.8
2020 35.4
Name: 최고기온(°C), Length: 108, dtype: float64
1950, 1953년 데이터 제거¶
df_seoul_max.drop(index=[1950,1953], inplace=True)
시각화¶
plt.plot(df_seoul_max, 'r.-')
plt.title('서울시 연 최고기온의 변화', size=15)
plt.show()
💡올랐다가 내렸다가 다시 오르는 곡선 형태를 띄고있다.
💡그래프를 통해 110년 동안의 기온 변화를 한눈에 볼 수 있다.
서울시 연간 평균기온, 최저기온, 최고기온 비교¶
서브플롯으로 각 그래프의 추세 비교¶
fig = plt.figure(figsize=(15,5), facecolor='snow')
plt.subplot(131)
plt.plot(df_seoul_mean, 'g.-')
plt.title('서울시 연 평균기온 변화', size=15)
plt.xlabel('연도')
plt.ylabel('평균기온')
plt.grid(ls=':')
plt.subplot(132)
plt.plot(df_seoul_min, 'b.-')
plt.title('서울시 연 최저기온 변화', size=15)
plt.xlabel('연도')
plt.ylabel('최저기온')
plt.grid(ls=':')
plt.subplot(133)
plt.plot(df_seoul_max, 'r.-')
plt.title('서울시 연 최고기온 변화', size=15)
plt.xlabel('연도')
plt.ylabel('최고기온')
plt.grid(ls=':')
fig.suptitle('서울시 기온 변화', size=20, fontweight='bold')
fig.tight_layout()
plt.show()
평균, 최저, 최고기온의 변동 폭 비교¶
# 세 개의 플롯을 하나의 axes에 그리기
plt.figure(figsize=(15,7))
plt.plot(df_seoul_mean, 'g.-', label='평균기온')
plt.plot(df_seoul_min, 'b.-', label='최저기온')
plt.plot(df_seoul_max, 'r.-', label='최고기온')
plt.legend(loc=(0,1.01), ncol=3, fontsize=12, edgecolor='k')
plt.title('서울시 기온 변화', size=20, pad=30)
plt.xticks(range(1910,2021,5))
plt.yticks(range(-25,42,5))
plt.grid(ls=':')
# 수평선 ( 각 플롯의 최대, 최소값의 위치에 수평선 그리기 )
plt.axhline(df_seoul_mean.min(), color='gray', ls='--')
plt.axhline(df_seoul_mean.max(), color='gray', ls='--')
plt.axhline(df_seoul_min.min(), color='gray', ls='--')
plt.axhline(df_seoul_min.max(), color='gray', ls='--')
plt.axhline(df_seoul_max.min(), color='gray', ls='--')
plt.axhline(df_seoul_max.max(), color='gray', ls='--')
plt.show()
[92차시]데이터 추출 및 전처리
[93차시]지점별 연 평균기온 시각화
[94차시]지점별 연 최저기온,최고기온 시각화
[95차시]지점별 기온분포 시각화
import matplotlib.pyplot as plt
import pandas as pd
plt.rcParams['font.family']='Malgun Gothic'
plt.rcParams['axes.unicode_minus']=False
데이터 준비 및 확인¶
- 기상자료개방포털 > 데이터 > 기상관측 > 지상 > 종관기상관측(ASOS)
https://data.kma.go.kr/data/grnd/selectAsosRltmList.do?pgmNo=36
[ 자료형태 ] 일자료
[ 지점 ] 전체
[ 자료 ] 기온>최저,최고,평균
[ 기간 ] 1911~2020 (10년단위로 나누어 다운로드)
데이터프레임 생성¶
df_1911 = pd.read_csv('data/1911-1920 일별 기온.csv', encoding='cp949')
df_1921 = pd.read_csv('data/1921-1930 일별 기온.csv', encoding='cp949')
df_1931 = pd.read_csv('data/1931-1940 일별 기온.csv', encoding='cp949')
df_1941 = pd.read_csv('data/1941-1950 일별 기온.csv', encoding='cp949')
df_1951 = pd.read_csv('data/1951-1960 일별 기온.csv', encoding='cp949')
df_1961 = pd.read_csv('data/1961-1970 일별 기온.csv', encoding='cp949')
df_1971 = pd.read_csv('data/1971-1980 일별 기온.csv', encoding='cp949')
df_1981 = pd.read_csv('data/1981-1990 일별 기온.csv', encoding='cp949')
df_1991 = pd.read_csv('data/1991-2000 일별 기온.csv', encoding='cp949')
df_2001 = pd.read_csv('data/2001-2010 일별 기온.csv', encoding='cp949')
df_2011 = pd.read_csv('data/2011-2020 일별 기온.csv', encoding='cp949')
df = pd.read_csv('C:/code/data/1911-1920 일별 기온.csv, encoding = 'cp949')
for i in range(1921, 2021, 10) :
df1 = pd.read_csv(f'C:/code/data/{i}-{i + 9} 일별 기온.csv', encoding = 'cp949')
df = pd.concat([df, df1], axis = 0)
df.to_csv('1911-2020 일별 기온.csv', encoding = 'cp949')
# 데이터프레임 연결하기
df = pd.concat([df_1911,df_1921,df_1931,df_1941,df_1951,df_1961,df_1971,df_1981,df_1991,df_2001,df_2011]
,ignore_index=True)
데이터 확인¶
df.shape
(1596835, 6)
df['지점명'].unique()
array(['강릉', '서울', '인천', '대구', '전주', '부산', '목포', '제주', '울릉도', '추풍령', '광주', '포항', '울산', '여수', '속초', '춘천', '수원', '서산', '청주', '대전', '군산', '통영', '서귀포', '진주', '임실', '정읍', '대관령', '원주', '충주', '울진', '안동', '완도', '성산', '강화', '양평', '이천', '인제', '홍천', '삼척', '제천', '보은', '천안', '보령', '부여', '금산', '부안', '남원', '고창군', '주암', '장흥', '해남', '고흥', '성산포', '영주', '문경', '영덕', '의성', '구미', '영천', '거창', '합천', '밀양', '산청', '거제', '남해', '철원', '관악산', '창원', '고산', '태백', '장수', '봉화', '동두천', '백령도', '동해', '영월', '무안', '흑산도', '파주', '북강릉', '상주', '고창', '진도(첨찰산)', '정선군', '영광군', '김해시', '순창군', '북창원', '양산시', '보성군', '강진군', '의령군', '함양군', '청송군', '경주시', '북춘천', '순천', '대구(기)', '홍성', '세종', '광양시', '진도군'], dtype=object)
df['지점명'].nunique()
102
데이터타입 확인/변경¶
df.dtypes
지점 int64 지점명 object 일시 object 평균기온(°C) float64 최저기온(°C) float64 최고기온(°C) float64 dtype: object
df['일시'] = pd.to_datetime(df['일시'])
df.dtypes
지점 int64 지점명 object 일시 datetime64[ns] 평균기온(°C) float64 최저기온(°C) float64 최고기온(°C) float64 dtype: object
2020년 지점별 기온 데이터 추출 및 전처리¶
2020년 기온 데이터 추출하여 서브셋 만들기¶
- 조건으로 데이터를 추출한다.
- 필요한 컬럼을 추출한다.
- .copy()를 사용하여 카피본으로 서브셋을 만든다.
# 서브셋 만들기
df_2020 = df[df['일시'].dt.year==2020].copy()
df_2020
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) | |
---|---|---|---|---|---|---|
1257132 | 90 | 속초 | 2020-01-01 | 0.8 | -3.4 | 4.8 |
1257133 | 90 | 속초 | 2020-01-02 | 2.8 | -2.1 | 6.6 |
1257134 | 90 | 속초 | 2020-01-03 | 4.7 | 0.8 | 8.5 |
1257135 | 90 | 속초 | 2020-01-04 | 4.0 | 1.1 | 8.1 |
1257136 | 90 | 속초 | 2020-01-05 | 3.1 | -0.6 | 8.8 |
... | ... | ... | ... | ... | ... | ... |
1596830 | 295 | 남해 | 2020-12-27 | 4.4 | 2.5 | 6.0 |
1596831 | 295 | 남해 | 2020-12-28 | 4.7 | 1.1 | 11.5 |
1596832 | 295 | 남해 | 2020-12-29 | 5.4 | 1.0 | 11.2 |
1596833 | 295 | 남해 | 2020-12-30 | -3.0 | -5.4 | 1.6 |
1596834 | 295 | 남해 | 2020-12-31 | -1.3 | -7.4 | 2.8 |
34767 rows × 6 columns
# 지점별 데이터 개수 카운트
df_2020['지점명'].value_counts()
속초 366 세종 366 순창군 366 김해시 366 영광군 366 ... 군산 366 포항 366 남해 366 북창원 365 진도군 364 Name: 지점명, Length: 95, dtype: int64
결측치 확인¶
# 컬럼별 결측치 개수 확인
df_2020.isnull().sum()
지점 0 지점명 0 일시 0 평균기온(°C) 36 최저기온(°C) 0 최고기온(°C) 1 dtype: int64
# 결측치 데이터 확인
df_2020[(df_2020['평균기온(°C)'].isnull()) | (df_2020['최고기온(°C)'].isnull())]
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) | |
---|---|---|---|---|---|---|
1324672 | 130 | 울진 | 2020-08-23 | NaN | 22.1 | 27.9 |
1335657 | 135 | 추풍령 | 2020-09-18 | NaN | 13.8 | 23.7 |
1335664 | 135 | 추풍령 | 2020-09-25 | NaN | 11.6 | 23.6 |
1350113 | 140 | 군산 | 2020-04-15 | NaN | 4.7 | 17.0 |
1350343 | 140 | 군산 | 2020-12-01 | NaN | -1.5 | 8.4 |
1394163 | 172 | 고창 | 2020-11-19 | NaN | 11.5 | 22.2 |
1397420 | 174 | 순천 | 2020-01-18 | NaN | -1.7 | 4.1 |
1435973 | 211 | 인제 | 2020-02-20 | NaN | -2.7 | 9.8 |
1446909 | 217 | 정선군 | 2020-01-30 | NaN | -1.2 | 6.1 |
1461703 | 235 | 보령 | 2020-07-30 | NaN | 22.9 | 26.3 |
1477035 | 244 | 임실 | 2020-12-16 | NaN | -8.7 | -3.2 |
1480541 | 245 | 정읍 | 2020-07-22 | NaN | 20.6 | 23.8 |
1483995 | 247 | 남원 | 2020-01-05 | NaN | -6.2 | 9.1 |
1484013 | 247 | 남원 | 2020-01-23 | NaN | 2.6 | 8.7 |
1484035 | 247 | 남원 | 2020-02-14 | NaN | 2.0 | 18.3 |
1505954 | 255 | 북창원 | 2020-02-17 | NaN | -2.8 | 2.9 |
1510142 | 257 | 양산시 | 2020-02-13 | NaN | 6.5 | 14.0 |
1524884 | 261 | 해남 | 2020-06-25 | NaN | 21.4 | 22.1 |
1524885 | 261 | 해남 | 2020-06-26 | NaN | 18.8 | 28.4 |
1532071 | 263 | 의령군 | 2020-02-27 | NaN | 5.5 | 10.7 |
1532072 | 263 | 의령군 | 2020-02-28 | NaN | 4.0 | 7.1 |
1532244 | 263 | 의령군 | 2020-08-18 | NaN | 23.5 | 31.6 |
1532355 | 263 | 의령군 | 2020-12-07 | NaN | -3.7 | 12.6 |
1532372 | 263 | 의령군 | 2020-12-24 | NaN | -1.9 | 13.9 |
1535781 | 264 | 함양군 | 2020-04-25 | NaN | 1.3 | 23.5 |
1535783 | 264 | 함양군 | 2020-04-27 | NaN | 1.6 | 19.0 |
1535784 | 264 | 함양군 | 2020-04-28 | NaN | 1.5 | 21.0 |
1539616 | 266 | 광양시 | 2020-12-26 | NaN | 4.3 | 11.0 |
1541863 | 268 | 진도군 | 2020-07-03 | NaN | 19.0 | 21.4 |
1549336 | 272 | 영주 | 2020-12-18 | NaN | -9.3 | 1.1 |
1556618 | 276 | 청송군 | 2020-11-26 | NaN | -2.7 | NaN |
1560289 | 277 | 영덕 | 2020-12-15 | NaN | -8.9 | -1.3 |
1563804 | 278 | 의성 | 2020-07-30 | NaN | 21.5 | 25.1 |
1567564 | 279 | 구미 | 2020-11-14 | NaN | 2.8 | 18.6 |
1570960 | 281 | 영천 | 2020-03-02 | NaN | 0.5 | 11.3 |
1592911 | 294 | 거제 | 2020-04-05 | NaN | 4.6 | 14.5 |
# 결측치가 있는 데이터의 지점별 카운팅
df_2020[(df_2020['평균기온(°C)'].isnull()) | (df_2020['최고기온(°C)'].isnull())].value_counts('지점명')
지점명 의령군 5 함양군 3 남원 3 해남 2 추풍령 2 군산 2 청송군 1 진도군 1 정읍 1 정선군 1 임실 1 인제 1 의성 1 거제 1 울진 1 고창 1 영주 1 영덕 1 양산시 1 순천 1 북창원 1 보령 1 구미 1 광양시 1 영천 1 dtype: int64
# 결측치 제거
df_2020.dropna(inplace=True)
# 결측치 잘 제거되었는지 확인
df_2020.isnull().sum()
지점 0 지점명 0 일시 0 평균기온(°C) 0 최저기온(°C) 0 최고기온(°C) 0 dtype: int64
# 지점별 데이터 개수 확인
df_2020['지점명'].value_counts()
속초 366 완도 366 금산 366 부여 366 천안 366 ... 군산 364 진도군 363 함양군 363 남원 363 의령군 361 Name: 지점명, Length: 95, dtype: int64
지점별 연평균 기온 시각화¶
- 연 평균기온이 높은 지역은 어디일까?
- 연 평균기온이 낮은 지역은 어디일까?
- 서울의 연 평균기온은 전국에서 어느정도 위치에 해당할까?
2020년도 지점별 연 평균기온 추출¶
- 지점별 연간 일 평균기온의 평균 계산
지점명으로 그룹핑하여 일평균기온의 평균 계산
df_2020_mean = df_2020.groupby('지점명')['평균기온(°C)'].mean().sort_values(ascending=False)
df_2020_mean
지점명 서귀포 16.770219 제주 16.744809 고산 16.076503 성산 15.981148 북창원 15.206593 ... 철원 10.976776 제천 10.973497 봉화 10.821038 태백 9.631421 대관령 7.787978 Name: 평균기온(°C), Length: 95, dtype: float64
시각화¶
# 지점별 연 평균기온
plt.figure(figsize=(20,5))
plt.bar(df_2020_mean.index, df_2020_mean.values, color='lightgreen')
plt.xticks(rotation=90)
# 최고, 평균, 최저 라인 표시
plt.axhline(df_2020_mean.max(), color='r', ls='--',
label='최고:'+str(round(df_2020_mean.max(),1)))
plt.axhline(df_2020_mean.min(), color='b', ls='--',
label='최저:'+str(round(df_2020_mean.min(),1)))
plt.axhline(df_2020_mean.mean(), color='g', ls='--',
label='평균:'+str(round(df_2020_mean.mean(),1)))
plt.legend(loc=(0,1.01), ncol=3, fontsize=12, edgecolor='k')
# 서울지역 표시
plt.bar('서울', df_2020_mean.loc['서울'], color='r')
plt.text('서울', df_2020_mean.loc['서울']+0.5, '서울('+str(round(df_2020_mean.loc['서울'],1))+')',
ha='center', fontsize=15)
plt.title('2020년 전국 지점별 연 평균기온', size=20, pad=30)
plt.show()
💡서귀포의 연 평균 기온이 가장 높고(16.8도), 대관령이 가장 낮다.(7.8도)
전국의 평균기온은 13.3도인데 서울은 이와 비슷하다.
지점별 연 최저기온, 최고기온 시각화¶
- 연 최저기온이 높은 지역은 어디일까? = 겨울이 따뜻하다
- 연 최저기온이 낮은 지역은 어디일까? = 겨울에 춥다
- 서울의 연 최저기온은 전국에서 어느정도 위치에 해당할까?
지점별 연 최저기온¶
지점별 연 최저기온 추출¶
# 지점명으로 그룹화하여 지점별 연 최저기온 추출
df_2020_cold = df_2020.groupby('지점명')['최저기온(°C)'].min().sort_values(ascending=False)
df_2020_cold
지점명 제주 -1.4 고산 -1.4 서귀포 -2.1 성산 -2.8 흑산도 -3.3 ... 홍천 -18.2 북춘천 -18.5 철원 -18.8 제천 -20.3 대관령 -24.0 Name: 최저기온(°C), Length: 95, dtype: float64
시각화¶
# 지점별 연 최저기온
plt.figure(figsize=(20,5))
plt.bar(df_2020_cold.index, df_2020_cold.values, color='skyblue')
plt.xticks(rotation=90)
plt.title('2020년 지점별 연 최저기온', size=20, pad=30)
# 최저, 평균, 최고지점 표시
plt.axhline(df_2020_cold.max(), color='r', ls='--', label='최고'+str(df_2020_cold.max()))
plt.axhline(df_2020_cold.mean(), color='g', ls='--', label='평균'+str(round(df_2020_cold.mean(),1)))
plt.axhline(df_2020_cold.min(), color='b', ls='--', label='최저'+str(df_2020_cold.min()))
plt.legend(loc=(0,1.01), ncol=3, fontsize=12, edgecolor='k')
# 서울 표시
plt.bar('서울', df_2020_cold.loc['서울'],color='r')
plt.text('서울', df_2020_cold.loc['서울']-1.5, '서울('+str(df_2020_cold.loc['서울'])+')'
, ha='center', fontsize=12)
plt.show()
💡겨울이 가장 따뜻한 곳은 제주도이고, 가장 추운 곳은 대관령이다
서울은 평균보다 약간 더 춥다.
지점별 연 최고기온¶
지점별 연 최고기온 추출¶
# 지점명으로 그룹화하여 지점별 연 최고기온 추출
df_2020_hot = df_2020.groupby('지점명')['최고기온(°C)'].max().sort_values(ascending=False)
df_2020_hot
지점명 양산시 37.8 대구 37.0 경주시 36.9 포항 36.9 북창원 36.9 ... 여수 32.6 울릉도 32.0 대관령 31.6 서귀포 31.3 백령도 30.5 Name: 최고기온(°C), Length: 95, dtype: float64
시각화¶
# 지점별 연 최고기온
plt.figure(figsize=(20,5))
plt.bar(df_2020_hot.index, df_2020_hot.values, color='pink')
plt.xticks(rotation=90)
plt.title('2020년 지점별 연 최고기온', size=20, pad=30)
# 최저, 평균, 최고지점 표시
plt.axhline(df_2020_hot.max(), color='r', ls='--', label='최고'+str(df_2020_hot.max()))
plt.axhline(df_2020_hot.mean(), color='g', ls='--', label='평균'+str(round(df_2020_hot.mean(),1)))
plt.axhline(df_2020_hot.min(), color='b', ls='--', label='최저'+str(df_2020_hot.min()))
plt.legend(loc=(0,1.01), ncol=3, fontsize=12, edgecolor='k')
# 서울 표시
plt.bar('서울', df_2020_hot.loc['서울'],color='r')
plt.text('서울', df_2020_hot.loc['서울']+0.5, '서울('+str(df_2020_hot.loc['서울'])+')'
, ha='center', fontsize=12)
plt.show()
💡서울의 최고기온은 연 평균보다 조금 높다.
지점별 기온 분포 시각화 - 히스토그램¶
서귀포, 서울, 대관령 서브셋 만들기¶
# 서귀포 서브셋
df_2020_sgp = df_2020[df_2020['지점명']=='서귀포'].copy()
df_2020_sgp
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) | |
---|---|---|---|---|---|---|
1417659 | 189 | 서귀포 | 2020-01-01 | 7.0 | 4.8 | 9.6 |
1417660 | 189 | 서귀포 | 2020-01-02 | 8.7 | 5.6 | 12.7 |
1417661 | 189 | 서귀포 | 2020-01-03 | 9.5 | 6.1 | 13.4 |
1417662 | 189 | 서귀포 | 2020-01-04 | 9.7 | 6.2 | 14.0 |
1417663 | 189 | 서귀포 | 2020-01-05 | 9.6 | 6.1 | 12.8 |
... | ... | ... | ... | ... | ... | ... |
1418020 | 189 | 서귀포 | 2020-12-27 | 10.9 | 9.9 | 11.9 |
1418021 | 189 | 서귀포 | 2020-12-28 | 11.7 | 7.9 | 15.5 |
1418022 | 189 | 서귀포 | 2020-12-29 | 12.5 | 9.9 | 15.2 |
1418023 | 189 | 서귀포 | 2020-12-30 | 0.7 | -2.1 | 10.0 |
1418024 | 189 | 서귀포 | 2020-12-31 | 1.8 | -1.3 | 4.3 |
366 rows × 6 columns
# 서울 서브셋
df_2020_seoul = df_2020[df_2020['지점명']=='서울'].copy()
df_2020_seoul
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) | |
---|---|---|---|---|---|---|
1295215 | 108 | 서울 | 2020-01-01 | -2.2 | -6.5 | 0.3 |
1295216 | 108 | 서울 | 2020-01-02 | 1.0 | -0.7 | 3.8 |
1295217 | 108 | 서울 | 2020-01-03 | -0.1 | -3.4 | 4.6 |
1295218 | 108 | 서울 | 2020-01-04 | 1.2 | -2.8 | 6.1 |
1295219 | 108 | 서울 | 2020-01-05 | 1.3 | -3.2 | 6.6 |
... | ... | ... | ... | ... | ... | ... |
1295576 | 108 | 서울 | 2020-12-27 | 5.8 | 1.4 | 10.0 |
1295577 | 108 | 서울 | 2020-12-28 | 6.7 | 4.2 | 11.4 |
1295578 | 108 | 서울 | 2020-12-29 | 0.1 | -6.2 | 4.3 |
1295579 | 108 | 서울 | 2020-12-30 | -10.9 | -12.9 | -6.2 |
1295580 | 108 | 서울 | 2020-12-31 | -8.9 | -12.9 | -5.0 |
366 rows × 6 columns
# 대관령 서브셋
df_2020_dgr = df_2020[df_2020['지점명']=='대관령'].copy()
df_2020_dgr
지점 | 지점명 | 일시 | 평균기온(°C) | 최저기온(°C) | 최고기온(°C) | |
---|---|---|---|---|---|---|
1273297 | 100 | 대관령 | 2020-01-01 | -6.5 | -11.5 | -2.5 |
1273298 | 100 | 대관령 | 2020-01-02 | -4.4 | -9.0 | -0.4 |
1273299 | 100 | 대관령 | 2020-01-03 | -3.2 | -7.4 | 2.5 |
1273300 | 100 | 대관령 | 2020-01-04 | -4.2 | -9.9 | 1.6 |
1273301 | 100 | 대관령 | 2020-01-05 | -5.5 | -14.2 | 4.6 |
... | ... | ... | ... | ... | ... | ... |
1273658 | 100 | 대관령 | 2020-12-27 | -1.1 | -4.2 | 5.3 |
1273659 | 100 | 대관령 | 2020-12-28 | 1.0 | -4.9 | 8.0 |
1273660 | 100 | 대관령 | 2020-12-29 | -3.0 | -8.0 | 4.5 |
1273661 | 100 | 대관령 | 2020-12-30 | -14.2 | -18.3 | -5.4 |
1273662 | 100 | 대관령 | 2020-12-31 | -14.5 | -20.2 | -8.5 |
366 rows × 6 columns
서귀포, 서울, 대관령 일 평균기온 히스토그램¶
💡plt.rcParams: 스타일 파라미터의 종류를 확인할 수 있다.
# 스타일 파라미터
plt.rcParams['hatch.color']='w'
# 서브플롯 만들기(plt.subplots()) & 축 통일
fig, ax = plt.subplots(1,3, figsize=(15,5), sharex=True, sharey=True)
# 서귀포 일평균기온 히스토그램
ax[0].hist(df_2020_sgp['평균기온(°C)'], rwidth=0.9, hatch='//')
ax[0].set_title('2020년 서귀포 일 평균기온 분포')
ax[0].set_xlabel('일 평균기온(°C)')
ax[0].set_ylabel('일수')
# 서울 일평균기온 히스토그램
ax[1].hist(df_2020_seoul['평균기온(°C)'], rwidth=0.9, hatch='--')
ax[1].set_title('2020년 서울 일 평균기온 분포')
ax[1].set_xlabel('일 평균기온(°C)')
# 대관령 일평균기온 히스토그램
ax[2].hist(df_2020_dgr['평균기온(°C)'], rwidth=0.9, hatch='xx')
ax[2].set_title('2020년 대관령 일 평균기온 분포')
ax[2].set_xlabel('일 평균기온(°C)')
# 0°C 수직선 표시
ax[0].axvline(0,color='k', ls='--')
ax[1].axvline(0,color='k', ls='--')
ax[2].axvline(0,color='k', ls='--')
plt.tight_layout()
plt.show()
💡서귀포는 일 평균기온이 영하 아래로 내려간적이 없다. 기온의 변동폭이 좁다.
💡서울은 25도 정도에 기온이 가장 많이 분포해있으며, 겨울에는 영하로 기온이 내려가기도 한다.
💡대관령은 영하 부근에 기온이 많이 분포해있으며, 대체로 기온이 낮다.
지점별 기온분포 시각화 - 박스플롯, 바이올린플롯¶
- 서귀포, 서울, 대관령 지점 2020년 평균기온 서브셋
# 서브플롯 그리기
fig = plt.figure(figsize=(15,5))
ax1 = fig.add_subplot(1,2,1)
ax2 = fig.add_subplot(1,2,2)
# 박스플롯
ax1.boxplot([df_2020_sgp['평균기온(°C)'],df_2020_seoul['평균기온(°C)'],df_2020_dgr['평균기온(°C)']])
# 바이올린플롯
plt.show()
새로 알게된 점
다른분들의 TIL을 둘러보다가 주피터 노트북을 티스토리로 가져올 수 있다는 것을 알게 되었다. (감사합니다☺️)
[참고링크]
Jupyter Notebook에서 처리한 작업을 Tistory로 손쉽게 가져오기
주피터 노트북에서 작업한 내용을 깔끔하게 티스토리에 정리하는 노하우를 공개하겠다. (1) 주피터 노트북에서 File 탭에서 Print Preview를 누른다. (2) 새로운 창이 열리면서 주피터에서 작업한 내
jfun.tistory.com
[적용방법]
- 주피터 노트북 File > Print Preview
- 새로운 창이 열리면 Ctrl + U
- 작업한 내용이 html로 보이게 되는데 Ctrl + A로 전체 선택 후, Ctrl + C로 복사
- 티스토리 화면 우측 상단 기본모드 > HTML로 들어간 후 원하는 위치에 붙여넣기
위 링크에 5번은 각 셀의 크기를 조정하는 것이라 굳이 바꾸지 않아도 괜찮다.
+) 한두개 올리는게 아니라면 주피터 노트북 여러개를 티스토리로 가져오는 것은 추천하지 않는다. 여러개를 가져오다보니 자꾸 깨진다...🥲 해당 기능은 분석 파트 정도에서 사용하면 좋을 것 같다.
[파트너간 상보적 학습 및 강의 내용 리뷰]
이번 시간에는 각자 멘토링 시간에 질문할 거리를 생각해보았다. 우리끼리 고민해본 후 해결하지 못한 문제는 질문하기로 했다. 우리조의 질문은 첫째, 러그 플롯의 의미와 활용방법. 둘째, 여러 개의 데이터프레임 쉽게 불러오는 법. 셋째, 데이터 인사이트 잘찾는법. 넷째, 데이터를 잘 표현할 수 있는 그래프 찾는법이었다.
그리고 주피터 노트북을 티스토리에서 불러오는 과정에서 자꾸 깨지는 오류가 발생했는데 마침 우리 조에 티스토리로 주피터 노트북을 옮기신 분이 계셔서 여쭤봤더니 html을 기본모드로 바꾸면 주피터 노트북이 깨진다고 한다‼️ 다음 글부터는 주피터노트북을 한번에 html형태로 가져와서 업로드해야겠다. 그리고 한분은 코드를 깃허브에 관리한다고 하셔서 나도 깃허브에 코드를 올려야겠다고 생각했다.
멘토링 시간 질문 및 답변
1️⃣ 러그 플롯의 의미와 활용방법
x축의 분포를 확인할 수 있다. 그런데 정말 y축은 왜나오는걸까?
2️⃣ 여러 개의 데이터프레임 쉽게 불러오는 법
같은 조 분이 알려주셨다..! 완전 코딩 천재!!!
df = pd.read_csv('C:/code/data/1911-1920 일별 기온.csv, encoding = 'cp949') # 처음(1911-1920년) 데이터 프레임
for i in range(1921, 2021, 10) : # 1921년부터 10년 단위로 반복해줌
df1 = pd.read_csv(f'C:/code/data/{i}-{i + 9} 일별 기온.csv', encoding = 'cp949') # 더할 데이터프레임
df = pd.concat([df, df1], axis = 0) # 기존 데이터프레임과 더하기
df.to_csv('1911-2020 일별 기온.csv', encoding = 'cp949') # 전체 데이터프레임 저장
잘 이해가 안가서 설명해주실 수 있냐고 여쭤보니 친절하게 설명도 해주셨다👼 감사합니다💕
3️⃣ 데이터 인사이트 잘찾는법
도메인 지식(배경 지식)이 중요하다.
기술적 역량
4️⃣ 데이터를 잘 표현할 수 있는 그래프 찾는법
Matplotlib 공식 홈페이지 참고
Examples — Matplotlib 3.6.3 documentation
Examples This page contains example plots. Click on any image to see the full image and source code. For longer tutorials, see our tutorials page. You can also find external resources and a FAQ in our user guide. Lines, bars and markers Images, contours an
matplotlib.org
Seaborn 공식 홈페이지 참고
Example gallery — seaborn 0.12.2 documentation
seaborn.pydata.org
우리 조 질문 모두 해결!
* 유데미 큐레이션 바로가기 : https://bit.ly/3HRWeVL
* STARTERS 취업 부트캠프 공식 블로그 : https://blog.naver.com/udemy-wjtb
💡본 후기는 유데미-웅진씽크빅 취업 부트캠프 4기 데이터분석/시각화 학습 일지 리뷰로 작성되었습니다.
'교육 > 유데미 스타터스 4기' 카테고리의 다른 글
[👩💻TIL 8일차 ] 유데미 스타터스 취업 부트캠프 4기 (0) | 2023.02.15 |
---|---|
[👩💻TIL 7일차 ] 유데미 스타터스 취업 부트캠프 4기 (0) | 2023.02.14 |
유데미 스타터스 취업 부트캠프 4기 - 데이터분석/시각화(태블로) 1주차 학습 일지 (0) | 2023.02.10 |
[👩💻TIL 5일차 ] 유데미 스타터스 취업 부트캠프 4기 (0) | 2023.02.10 |
[👩💻TIL 4일차 ] 유데미 스타터스 취업 부트캠프 4기 (0) | 2023.02.09 |