Bike Sharing Demand 데이터셋 파이썬으로 간단하게 살펴보기 | 코드스테이츠 PMB 13기
Table of Contents
1. 기본 환경설정 + 파일 불러오기¶
- 나는 이번 과제로 워싱턴 DC의 자전거 렌탈 데이터셋을 가져왔다.
- 해당 데이터로 competition에 참여할 수 있으며 타이타닉과 와인 데이터와 더불어 유명한? 제너럴하게 많이 다루는 자료인 것 같다.
- 맨 처음에는 Students mental health 데이터를 가져와 분석하려고 했으나 모든 변수가 객체형이고(숫자형으로 바꿔줘야) 관측치가 없는 Null값도 존재했다.
그리고 학년 칼럼 안의 데이터가 일관된 형식이 아니라 형식도 통일시켜야 했다.
그리고 무엇보다도 데이터의 크기가 너무 작아 (101행) 분석이 무의미하지 않나..라는 생각이 들었다. - 데이터 샘플의 분포도 일관되지 않았다. 4학년의 샘플의 수는 8개, 1학년 샘플의 수는 40개가 넘었다.
샘플 불균형을 맞추기 위해 샘플링도 해야하고..아무튼 과제가 의도한 난이도에 비해 너무 많은 것들을 고려해야 해서 결국에는 패스했다.
그리고 널값도 없고 직관적으로 해석하기도 편한 자전거 수요 데이터셋을 선택하게 되었다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
from matplotlib.pylab import rcParams
rcParams['figure.figsize'] = 17, 8
rcParams['font.family'] = 'AppleGothic'
import warnings
warnings.filterwarnings(action='ignore')
bike = pd.read_csv('biketrain.csv', parse_dates=['datetime'])
print(bike.shape)
bike.head()
(10886, 12)
datetime | season | holiday | workingday | weather | temp | atemp | humidity | windspeed | casual | registered | count | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2011-01-01 00:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 81 | 0.0 | 3 | 13 | 16 |
1 | 2011-01-01 01:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 8 | 32 | 40 |
2 | 2011-01-01 02:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 5 | 27 | 32 |
3 | 2011-01-01 03:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 3 | 10 | 13 |
4 | 2011-01-01 04:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 0 | 1 | 1 |
2. 칼럼 정보 확인 + 가설 설정¶
2.1 칼럼 확인¶
bike.columns
Index(['datetime', 'season', 'holiday', 'workingday', 'weather', 'temp',
'atemp', 'humidity', 'windspeed', 'casual', 'registered', 'count'],
dtype='object')
2.2 칼럼 별 상세정보¶
(1) datetime: hourly date + timestamp
(2) season: 1 = spring, 2 = summer, 3 = fall, 4 = winter
(3) holiday: whether the day is considered a holiday
(4) workingday: whether the day is neither a weekend nor holiday
(5) weather
- 1: Clear, Few clouds, Partly cloudy, Partly cloudy
- 2: Mist + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist
- 3: Light Snow, Light Rain + Thunderstorm + Scattered clouds, Light Rain + Scattered clouds
- 4: Heavy Rain + Ice Pallets + Thunderstorm + Mist, Snow + Fog
(6) temp - temperature in Celsius
(7) atemp - "feels like" temperature in Celsius
(8) humidity - relative humidity
(9) windspeed - wind speed
(10) casual - number of non-registered user rentals initiated
(11) registered - number of registered user rentals initiated
(12) count - number of total rentals
2.3 가설 설정¶
- A. 여름 겨울보다 봄 가을에 사용자수가 더 많을 것이다.
- B. 평일보다는 주말에 사용자수가 더 많을 것이다.
- C. 날씨가 좋으면 사용자수가 더 많을 것이다.
- D. 습도가 높을수록 사용자수가 적을 것이다. (버스나 택시를 더 탈 것)
- E. 바람 속도가 높을수록 사용자수가 적을 것이다.
3. 데이터 전처리¶
- 날짜 정보가 datetime이라는 칼럼 안에 연도, 월, 일, 시긴, 분, 초(대여 시작 시점) 정보가 하나로 합쳐져 있다.
- 날짜 정보를 세분화해서 각각의 칼럼으로 표현하기 위해서 날짜 데이터를 파싱할 것이다.
- 파싱이란? https://na27.tistory.com/230
- 쉽게 말하면 데이터를 원하는 단위로 잘게 쪼개 활용할 수 있게끔 만드는 것.
3.1 날짜 데이터 파싱하기¶
# 새로운 칼럼을 생성해 년도, 월, 일, 시간, 분, 초로 세분화해 저장하기
bike['year'] = bike.datetime.dt.year
bike['month'] = bike.datetime.dt.month
bike['day'] = bike.datetime.dt.day
bike['hour'] = bike.datetime.dt.hour
bike['minute'] = bike.datetime.dt.minute
bike['second'] = bike.datetime.dt.second
# 변경사항 확인하기
bike.head()
datetime | season | holiday | workingday | weather | temp | atemp | humidity | windspeed | casual | registered | count | year | month | day | hour | minute | second | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2011-01-01 00:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 81 | 0.0 | 3 | 13 | 16 | 2011 | 1 | 1 | 0 | 0 | 0 |
1 | 2011-01-01 01:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 8 | 32 | 40 | 2011 | 1 | 1 | 1 | 0 | 0 |
2 | 2011-01-01 02:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 5 | 27 | 32 | 2011 | 1 | 1 | 2 | 0 | 0 |
3 | 2011-01-01 03:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 3 | 10 | 13 | 2011 | 1 | 1 | 3 | 0 | 0 |
4 | 2011-01-01 04:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 0 | 1 | 1 | 2011 | 1 | 1 | 4 | 0 | 0 |
3.2 결측치 확인하기¶
# 데이터타입 확인하기 전부 실수 혹은 정수형 데이터임을 확인할 수 있다.
bike.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10886 entries, 0 to 10885
Data columns (total 18 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 datetime 10886 non-null datetime64[ns]
1 season 10886 non-null int64
2 holiday 10886 non-null int64
3 workingday 10886 non-null int64
4 weather 10886 non-null int64
5 temp 10886 non-null float64
6 atemp 10886 non-null float64
7 humidity 10886 non-null int64
8 windspeed 10886 non-null float64
9 casual 10886 non-null int64
10 registered 10886 non-null int64
11 count 10886 non-null int64
12 year 10886 non-null int64
13 month 10886 non-null int64
14 day 10886 non-null int64
15 hour 10886 non-null int64
16 minute 10886 non-null int64
17 second 10886 non-null int64
dtypes: datetime64[ns](1), float64(3), int64(14)
memory usage: 1.5 MB
# 결측치 없는 아주 착한 데이터셋. 별도의 전처리 작업이 필요없다.
bike.isnull().sum()
datetime 0
season 0
holiday 0
workingday 0
weather 0
temp 0
atemp 0
humidity 0
windspeed 0
casual 0
registered 0
count 0
year 0
month 0
day 0
hour 0
minute 0
second 0
dtype: int64
4. 가설을 시각화 자료를 통해 확인하기¶
A. 여름 겨울보다 봄 가을에 사용자수가 더 많을 것이다.¶
plt.title('월별 사용자수 분포', fontsize=20)
sns.barplot(data=bike, x='month', y='count')
<AxesSubplot:title={'center':'월별 사용자수 분포'}, xlabel='month', ylabel='count'>
# 연도 구분이 안되고 있음. 연도별 월 사용자수 정보를 알기 위해
# year_month 칼럼을 생성
# 데이터를 합치는 내용의 concat_year_month 함수를 생성
def concat_year_month(datetime):
return '{0}{1}'.format(datetime.year, datetime.month)
# 연도 월 정보가 하나로 합쳐진 새로운 칼럼 year_month를 생성
bike['year_month'] = bike.datetime.apply(concat_year_month)
# 칼럼이 적절하게 생성됐는지 확인
bike.head()
datetime | season | holiday | workingday | weather | temp | atemp | humidity | windspeed | casual | registered | count | year | month | day | hour | minute | second | year_month | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2011-01-01 00:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 81 | 0.0 | 3 | 13 | 16 | 2011 | 1 | 1 | 0 | 0 | 0 | 20111 |
1 | 2011-01-01 01:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 8 | 32 | 40 | 2011 | 1 | 1 | 1 | 0 | 0 | 20111 |
2 | 2011-01-01 02:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 5 | 27 | 32 | 2011 | 1 | 1 | 2 | 0 | 0 | 20111 |
3 | 2011-01-01 03:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 3 | 10 | 13 | 2011 | 1 | 1 | 3 | 0 | 0 | 20111 |
4 | 2011-01-01 04:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 0 | 1 | 1 | 2011 | 1 | 1 | 4 | 0 | 0 | 20111 |
# 막대그래프로 시각화. 연도-월 별 대여 횟수를 확인
plt.title('연도-월별 사용자수 분포', fontsize=20)
sns.barplot(data=bike, x='year_month', y='count')
<AxesSubplot:title={'center':'연도-월별 사용자수 분포'}, xlabel='year_month', ylabel='count'>
- 내가 불러온 데이터셋은 워싱턴 D.C의 렌탈 정보다. 찾아보니 워싱턴은 6월부터 10월까지 활동하기 좋은 날씨라고 한다.
- 위의 표를 보면 날씨가 온화해짐에 따라 점차 사용 횟수가 증가하고 추워지면 사용 횟수가 감소하고 있음을 확인할 수 있다.
- 2011년과 2012년 모두 동일한 양상을 보이고 있다.
- 2012년 수치가 전반적으로 높은 이유는 사업 규모가 커졌기 때문이라고 생각할 수 있다.
B. 평일보다는 주말에 사용자수가 더 많을 것이다.¶
# 초반에 별 생각없이 날짜별로 휴일 여부에 따른 횟수를 계산했다. 좀 더 생각해보면 의미가 없는 분류 기준..매달 휴일 기준이 달라지는데..
sns.barplot(data=bike, x='day', y='count', hue='workingday')
<AxesSubplot:xlabel='day', ylabel='count'>
# 일 하는 것과 쉬는 날 상관없이 자전거를 대여하는 양상이 비슷하다.
# 그래프 해석: 일 하는 날과 안 하는 날을 구분하고 각각의 대여 횟수를 카운팅. 카운팅 기준은 월 별로.
# 오른쪽 막대그래프 덩어리는 일 하는 날(파이썬에서는 거짓인 값이 0을 가진다)의 월별 대여 횟수를 구한 것.
sns.barplot(data=bike, x='workingday', y='count', hue='month')
<AxesSubplot:xlabel='workingday', ylabel='count'>
- 생각해보니 월, 달에 따라 휴일인 때가 있고 아닌 때가 있었다.
- 2011년, 2012년 주말 평일 구분을 해야 한다.
# 날짜에 따른 요일 인덱스를 반환하는 함수 weekday() 불러오기
# 요일에 따라 대응되는 숫자가 달라진다. 0은 월요일, 6이 일요일
import datetime
datetime.datetime.today()
datetime.datetime.today().weekday()
5
# https://runebook.dev/ko/docs/pandas/reference/api/pandas.series.dt.weekday
# dayofweek 칼럼을 생성하고 그 안에 날짜별 요일 정보 저장하기
bike['dayofweek'] = bike.datetime.dt.dayofweek
bike.head()
datetime | season | holiday | workingday | weather | temp | atemp | humidity | windspeed | casual | registered | count | year | month | day | hour | minute | second | year_month | dayofweek | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2011-01-01 00:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 81 | 0.0 | 3 | 13 | 16 | 2011 | 1 | 1 | 0 | 0 | 0 | 20111 | 5 |
1 | 2011-01-01 01:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 8 | 32 | 40 | 2011 | 1 | 1 | 1 | 0 | 0 | 20111 | 5 |
2 | 2011-01-01 02:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 5 | 27 | 32 | 2011 | 1 | 1 | 2 | 0 | 0 | 20111 | 5 |
3 | 2011-01-01 03:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 3 | 10 | 13 | 2011 | 1 | 1 | 3 | 0 | 0 | 20111 | 5 |
4 | 2011-01-01 04:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 0 | 1 | 1 | 2011 | 1 | 1 | 4 | 0 | 0 | 20111 | 5 |
# 파이썬은 엑셀과 다르게 0이 월요일이며 6이 일요일이다.
# 요일별 대여 횟수 계산하기
plt.title('요일별 대여 횟수 분포', fontsize=20)
sns.barplot(data=bike, x='dayofweek', y='count')
<AxesSubplot:title={'center':'요일별 대여 횟수 분포'}, xlabel='dayofweek', ylabel='count'>
- 요일별로 대여 횟수에 그렇게 큰 차이가 보이지는 않는다.
- 이것도 y축 범위에 따라 차이가 분명하게 보일수도..있겠지만 그것까지는 생각하지 않기로 했다.
- 아마 평일에는 출퇴근 용으로 자전거를 대여하고 주말에는 놀러가는 용도로 자전거를 대여하기 때문에 특별히 요일에 따른 대여 횟수 차이가 발생하지 않는 것 같다.
C. 날씨가 좋으면 사용자수가 더 많을 것이다.¶
plt.title('날씨 조건별 대여 횟수 분포', fontsize=20)
sns.barplot(data=bike, x='weather', y='count')
<AxesSubplot:title={'center':'날씨 조건별 대여 횟수 분포'}, xlabel='weather', ylabel='count'>
날씨 구분
1: Clear, Few clouds, Partly cloudy, Partly cloudy
2: Mist + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist
3: Light Snow, Light Rain + Thunderstorm + Scattered clouds, Light Rain + Scattered clouds
4: Heavy Rain + Ice Pallets + Thunderstorm + Mist, Snow + Fog
- 결과를 보면 날씨가 좋은 날에 대여하는 횟수가 가장 많은 것을 확인할 수 있다.
- 안개가 낀 날에는 상대적으로 작은 규모지만 나머지 세 조건 중에서 가장 많은 횟수를 보이고 있다. 안개 정도는 견디고 탈 수 있기 때문일까?
- 당황스러웠던 부분은 3번(약한 눈비)보다 4번(강한 눈비) 상황에서 사람들이 더 많이 자전거를 빌렸다는 점이었다.
생각해보니 우산을 챙기지 못한 사람들이 강하게 내리는 눈과 비를 빨리 피하기 위해 자전거를 빌렸을 수도 있겠다는 생각이 들었다.
약한 비나 눈은 오히려 맞으면서 여유롭게 이동하고 말이다.ㅋㅋ
D. 습도가 높을수록 사용자수가 적을 것이다. (버스나 택시를 더 탈 것)¶
sns.barplot(data=bike, x='humidity', y='count')
<AxesSubplot:xlabel='humidity', ylabel='count'>
- 습도가 높아질수록 대여 횟수가 감소함을 확인할 수 있다. 불쾌지수가 높으면 자전거를 탈 마음이 안 들어서 그런가?
E. 바람 속도가 높을수록 사용자수가 적을 것이다.¶
sns.barplot(data=bike, x='windspeed', y='count')
<AxesSubplot:xlabel='windspeed', ylabel='count'>
- 특별한 상관관계를 발견할 수 없다.
- 사실 이렇게 하나의 변수만 가지고 판단하는 건 굉장히 위험하다. 변수 간 상관관계를 고려해 동시에 고려하는 것이 좋겠지만..
- 과제의 목적에서 벗어나는 범위인 것 같아서 파이썬 복습 했다는 느낌으로 이번 과제를 마무리하려고 한다.
5. 결론¶
- 사람들은 날씨가 따뜻해지면 자전거를 빌리는 경향이 있다.
- 휴일 근로일 상관없이 자전거를 빌린다. 사람들은 여가 용도 외 출퇴근 목적으로도 자전거를 빌린다고 유추할 수 있다.
- 사람들은 날씨가 맑을 때 주로 자전거를 빌리지만 날씨가 극도로 안 좋을 때도 빌린다. 비바람을 피하기 위해서 사용하는 것이라고 유추할 수 있다.
- 습도가 높을수록 사람들이 자전거를 빌리지 않는다. 불쾌지수가 높아지면 자전거를 안 타는 거라고 유추할 수 있다.
- 바람 속도에 따른 뚜렷한 상관관계는 발견할 수 없었다. 다만 극단값 중 수치가 극도로 낮은 부분이 있는데 이에 대해서는 추가 조사가 필요할 것이다.
사실 제대로 하려면 바람 속도를 구간별로 범주화해서 살펴보는 것이 더 좋을 것이다. 하지만 오늘은 여기까지..ㅋㅋ
- 파이썬은 주기적으로 심폐소생술을 해줘야 한다. 영어든 컴퓨터 언어든 계속 써야 익숙해진다...
- 나름 이제는 익숙해졌다고 생각했는데 파일 불러오는 함수도 기억 안 나서 예전 자료들을 뒤적이느라 시간을 다 보냈다.
- 그리고 항상 에러가 나를 머리아프게 한다. 그래서 PM이 빅쿼리 같은 플랫폼을 사용하는 걸까..? 에러 뜨는 꼴 보면 컴퓨터를 집어던질 테니까..
'부트 캠프 > 📓 Daily Tasks' 카테고리의 다른 글
Apple Developer 홈페이지 구조 살펴보기 | 코드스테이츠 PMB 13기 (0) | 2022.08.08 |
---|---|
youpick = 🤍 유픽의 사업 단계와 전략 생각해보기 | 코드스테이츠 PMB 13기 (0) | 2022.08.06 |
네이버웹툰의 핵심 지표를 GA를 통해 확인해보기 | 코드스테이츠 PMB 13기 (0) | 2022.08.03 |
순도 100% 뇌피셜로 네이버웹툰 백엔드 살펴보기 | 코드스테이츠 PMB 13기 (0) | 2022.08.02 |
더리치(The Rich.)의 랜딩 페이지 살펴보고 변화 제안하기 | 코드스테이츠 PMB 13기 (0) | 2022.07.29 |