이번 필사 주제는 New York City Taxi Duration 이다.
이 대회는 뉴욕시에서 택시 여행의 총 승차 시간을 예측하는 모델을 구축하는 것이 목표이다.
AiswaryaRamachandran님의 커널을 참고하여 필사를 진행했다.
목록
New York City Taxi Duration (1)
1. 데이터 분석 준비
1) data description
2. 데이터 살펴보기
1) missing data 찾기
2) 분석을 위한 새로운 컬럼 생성
New York City Taxi Duration (2)
3. Exploratory Data Analysis
1) HeatMap
2) 시간, 요일
3) 거리, 지역, 속도
New York City Taxi Duration (3)
4. Feature Engineering
5. 모델 적용
1) 모델 세우기
2) 선형 모델 적용
3) 랜덤포레스트 적용
3. Exploratory Data Analysis
데이터 탐구 분석
plt.figure(figsize=(8,5))
sns.distplot(train['trip_duration_in_hour']).set_title("Distribution of Trip Duration")
plt.xlabel("Trip Duration (in hour)")
# 24시간 보다 더 긴 시간 여행한 컬럼 생성. 우리는 여기에다가 집중할 것이다.
outlier_trip_duration = train.loc[train['trip_duration_in_hour']>24]
outlier_trip_duration
train['trip_duration'].sort_values(ascending=False)
"""
주행 기간이 매우 높은 4개의 기록이 있지만 주행 거리는 매우 낮다. 이것들은 특이치 입니다.
하지만 이 여행들이 시작되거나 끝나는 특별한 장소가 있을까? 트립 지속시간도 편향되어 있으니 로그 변환을 해보자.
이러한 데이터도 테스트 데이터의 일부일 수 있으므로 분석에서 제거하지 않을 것이다.
"""
plt.figure(figsize=(8,5))
sns.distplot(np.log(train['trip_duration'].values)).set_title("Distribution of Trip Duration")
plt.title("Disribution of trip duration (sec) in Log Scale")
"""
여행 지속시간의 로그 변환은 정규 분포를 따른다.
대부분의 여행은 54초(4)에서 2980초(8) 사이에 있다.
이것은 대부분의 여행이 한 시간 동안 함께 한다는 것을 나타낸다.
그러나 1분도 안 되는 여행이 있어 자세히 살펴볼 필요가 있다.
100시간 동안 지속되는 여행이 있는데, 택시 타기가 뉴욕 안에 있어서 이상하다.
"""
1) HeatMap
Heatmap of common locations from where pickup and dropoff occurs
pickup = train.groupby(['pickup_latitude_round3', 'pickup_longitude_round3'])['id'].count().reset_index().rename(columns={'id' : 'Num_Trips'})
pickup.head()
pickup_map = folium.Map(location=[40.730610, -73.935242], zoom_start=10,)
# print (pickup.shape)
pickup.Num_Trips.values
pickup.Num_Trips = np.array(pickup.Num_Trips.values).astype('float64')
hm_wide = HeatMap(list(zip(pickup.pickup_latitude_round3.values, pickup.pickup_longitude_round3.values, pickup.Num_Trips.values)),
min_opacity=0.2,
radius = 5, blur =15,
max_zoom=1)
pickup_map.add_child(hm_wide)
pickup_map # json 오류로 출력 안됨...
city_long_border = (-74.03, -73.75)
city_lat_border = (40.53, 40.85)
fig, ax = plt.subplots(ncols=1, sharex=True, sharey=True)
ax.scatter(train['pickup_longitude'], train['pickup_latitude'], color='blue', label='train', alpha=0.1)
fig.suptitle('Lat Lng of Pickups in Train Data as Scatter Plot')
ax.set_ylabel('latitude')
ax.set_xlabel('longitude')
plt.ylim(city_lat_border)
plt.xlim(city_long_border)
drop=train.groupby(['dropoff_latitude_round3','dropoff_longitude_round3'])['id'].count().reset_index().rename(columns={'id':'Num_Trips'})
drop.head()
drop_map = folium.Map(location=[40.730610, -73.935242], zoom_start=10,)
hm_wide = HeatMap(list(zip(drop.dropoff_latitude_round3.values, drop.dropoff_longitude_round3.values, drop.Num_Trips)),
min_opacity=0.2,
radius=5, blur=15,
max_zoom=1)
drop_map.add_child(hm_wide)
drop_map
Dropoff Heatmap은 Pickup과 유사하다.
pickup이 point로부터 왔을때, trip 시간 heatmap
pickup= train.groupby(['pickup_latitude_round3', 'pickup_longitude_round3'])['trip_duration'].mean().reset_index().rename(columns={'trip_duration':'Avg_Trip_duration'})
pickup.head()
pickup_map = folium.Map(location= [40.730610, -73.935242], zoom_start=10,)
hm_wide = HeatMap(list(zip(pickup.pickup_latitude_round3.values, pickup.pickup_longitude_round3.values, pickup.Avg_Trip_duration)),
min_opacity=0.2,
radius=7, blur=15,
max_zoom=1)
pickup_map.add_child(hm_wide)
pickup_map
평균값은 트립이 JFK에서 시작할때 가장 높다. 좀더 들여다보면 맨하탄 이후임을 확인할 수 있다. JFK로부터 픽업은 높은 여행 시간을 가지는 경향이 있다.
2) 시간, 요일
어느 시간대가 높은가?
plt.figure(figsize=(8,5))
sns.countplot(x=train['pickup_hour']).set_title("Pick Hours Distribution")
이른 아침시간에는 적고, 오후 6~8시 사이가 피크임을 알 수 있다.
plt.figure(figsize=(8,5))
sns.countplot(x=train['dropoff_hour']).set_title("Dropoff Hours Distribution")
Drop 시간대도 pickup 시간대와 비슷하다.
전체 pickup 시간대 분포
plt.figure(figsize=(8,5))
plt.plot(train.groupby('pickup_date').count()[['id']], 'o-', label='train')
plt.title("Distribution of Pickups over time")
2016년 2월을 끝으로 pickup의 숫자는 떨어지는 것으로 보인다.
시간대 별로 trip 기간이 높은 것은 ?
avg_duration_hour = train.groupby(['pickup_hour'])['trip_duration'].mean()
plt.figure(figsize=(8,5))
plt.plot(train.groupby(['pickup_hour'])['trip_duration'].mean(), 'o-')
10~15시간대 사이가 duration이 증가한다.
요일별 pickup 배분 시간
plt.figure(figsize=(8,5))
sns.countplot(train['pickup_day_of_week'],
order=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'
, 'Saturday', 'Sunday'])
pickup 비율은 월요일이 제일 낮고, 화요일부터 증가하다가 금요일이 제일 높다.
요일별 평균 trip 기간
avg_duration_day = train.groupby(['pickup_day_of_week'])['trip_duration'].mean().reset_index().rename(columns={'trip_duration' : 'avg_trip_duration'})
plt.figure(figsize=(8,5))
sns.barplot(x='pickup_day_of_week', y='avg_trip_duration', data=avg_duration_day, order=['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday', 'Sunday']).set_title("Avg Trip Duration vs Pickup Days of Week")
목요일이 가장 높다.
3) 거리, 지역, 속도
Trip 거리 분포
train['trip_distance'].head()
train['trip_duration'].head()
# plt.figure(figsize=(8,5))
# sns.kdeplot(np.log(train['trip_distance'].values)).set_title("Trip Distance Distribution")
# sns.distplot(np.log(train['trip_distance'].values)).set_title("Distribution of Trip Duration") # cannot convert float infinity to integer
# sns.distplot(np.log(train['trip_distance'].values)).set_title("Trip Distance Distribution")
# plt.xlabel("Trip Distance (log)")
trip duration vs trip distance 비교
plt.scatter(np.log(train['trip_distance'].values),
np.log(train['trip_duration'].values),
color='blue', label='train'
)
plt.title("Distribution of Trip Distance vs Trip Duration")
plt.xlabel("Trip Distance (log scale)")
plt.ylabel("Trip Duration (log scale)")
제공해주는 함수를 통해 여행 방향을 측정해본다.
def calculateBearing(lat1, lng1, lat2, lng2):
R=6371
lng_delta_rad = np.radians(lng2-lng1)
lat1, lng1, lat2, lng2 = map(np.radians, (lat1, lng1, lat2, lng2))
y = np.sin(lng_delta_rad) * np.cos(lat2)
x = np.cos(lat1) * np.sin(lat2) - np.sin(lat1) * np.cos(lat2) * np.cos(lng_delta_rad)
return np.degrees(np.arctan2(y, x))
train['bearing'] = train.apply(lambda row : calculateBearing(row['pickup_latitude_round3'], row['pickup_longitude_round3'], row['dropoff_latitude_round3'], row['dropoff_longitude_round3']), axis=1)
# train['bearing'] = train.apply(lambda row : calculateBearing(row['pickup_latitude_round3'], row['pickup_longitude_round3'], row['dropoff_latitude_round3'], row['dropoff_longitude_round3']),axis=1)
bearing 분포
sns.kdeplot(train['bearing'])
Bearing vs Trip Duration
plt.figure(figsize=(8,5))
plt.scatter(train['bearing'].values, y=np.log(train['trip_duration'].values))
plt.xlabel("Bearing")
plt.ylabel("Trip Duration (log scale)")
-50 지점에서 outlier가 보인다.
Store와 FWD Flag 분포
train['store_and_fwd_flag'].value_counts()
plt.figure(figsize=(8,5))
sns.kdeplot(np.log(train.loc[train['store_and_fwd_flag']=='Y', 'trip_duration'].values), label='Store and Fwd = Yes')
sns.kdeplot(np.log(train.loc[train['store_and_fwd_flag']=='N', 'trip_duration'].values), label='Store and Fwd = No')
plt.title("Distribution of Store and Fwd Flas vs Trip Duration(log scale)")
plt.xlabel('Trip Duration (log scale)')
plt.ylabel('Destiny')
여행의 5~7시간 여행에서는 Store and Fwd Flag 값이 No가 더 많이 분포되어 있다.
클러스터내에 지역 그룹
이것은 아마 지역을 생성하는데 도움이 될것이다. 특정 지역으로부터 pickup은 아마 긴 trip 시간을 가질 수 있다.
coords = np.vstack((train[['pickup_latitude','pickup_longitude']].values,
train[['dropoff_latitude','dropoff_longitude']].values,
test[['pickup_latitude','pickup_longitude']].values,
test[['dropoff_latitude','dropoff_longitude']].values))
kmeans = KMeans(n_clusters=8, random_state=0).fit(coords)
train.loc[:, 'pickup_neighbourhood'] = kmeans.predict(train[['pickup_latitude', 'pickup_longitude']])
train.loc[:, 'dropoff_neighbourhood'] = kmeans.predict(train[['dropoff_latitude', 'dropoff_longitude']])
city_long_border = (-74.03, -73.75)
city_lat_border = (40.63, 40.85)
fig, ax = plt.subplots(ncols=1, sharex=True, sharey=True)
ax.scatter(train['pickup_longitude'], train['pickup_latitude'],
c=train['pickup_neighbourhood'], label='train', alpha=0.1)
fig.suptitle('Pickup Neighbourbood')
ax.set_ylabel('latitude')
ax.set_xlabel('longitude')
plt.ylim(city_lat_border)
plt.xlim(city_long_border)
예측한 값을 지도에 출력하였다.
각 지역안에서 pickup 수
plt.figure(figsize=(8,5))
sns.countplot(train['pickup_neighbourhood']).set_title("Distribution of Number of Pickups across Neighbourhood")
지역 0, 3, 6 순으로 pickup 수치가 크다.
avg_duration_neighbourhood = train.groupby(['pickup_neighbourhood'])['trip_duration'].mean().reset_index().rename(columns={'trip_duration':'avg_trip_duration'})
plt.figure(figsize=(8,5))
sns.barplot(x='pickup_neighbourhood', y='avg_trip_duration', data=avg_duration_neighbourhood).set_title("Avg Trip Duration vs Neighbourhood")
- 4, 2 지역 순으로 평균 trip duration 시간이 길다.
- 1, 5, 7은 위의 pickup neighbourhood 숫자가 0에 가까울지라도 평균 이용 기간은 높은 평균에 속한다.
평균 속도 분포
train['avg_speed_kph'] = train['trip_distance'] / train['trip_duration_in_hour']
plt.figure(figsize=(8,5))
sns.kdeplot(train['avg_speed_kph'].values).set_title("Distribution of Average Speed (in kph)")
print("Average speed is", np.mean(train['avg_speed_kph']), "kph")
일주일의 요일 평균 속도 - 교통 속도를 의미함.
avg_speed_per_day = train.groupby(['pickup_day_of_week'])['avg_speed_kph'].mean().reset_index()
plt.figure(figsize=(8,5))
sns.barplot(x='pickup_day_of_week', y='avg_speed_kph', data=avg_speed_per_day, order=['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday', 'Sunday']).set_title("Avg Speed (kph) vs Pickup Days of Week")
일요일과 월요일에 평균 속도가 높다.
'Competition > Kaggle' 카테고리의 다른 글
[kaggle][필사] New York City Taxi Duration (3) (0) | 2020.10.05 |
---|---|
[kaggle][필사] New York City Taxi Duration (1) (0) | 2020.10.02 |
[kaggle][필사] Statoil/C-CORE Iceberg Classifier Challenge (0) | 2020.09.25 |