import pandas as pd
import folium
To test that everything is working, let’s pull up a map of New York City and add a circle marker.
folium_map = folium.Map(location=[40.738, -73.98],
zoom_start=13,
tiles="CartoDB dark_matter")
folium.CircleMarker(location=[40.738, -73.98],fill=True).add_to(folium_map)
folium_map
Next, we’ll load some data. The NYC bike share program makes its data public, you can download it here: https://www.citibikenyc.com/system-data. Just one month of data will do for this example.
We’ll use pandas to load the data into python, we’ll convert time strings into DateTime objects
bike_data = pd.read_csv("201610-citibike-tripdata.csv")
bike_data["Start Time"] = pd.to_datetime(bike_data["Start Time"])
bike_data["Stop Time"] = pd.to_datetime(bike_data["Stop Time"])
bike_data["hour"] = bike_data["Start Time"].map(lambda x: x.hour)
bike_data.head()
Trip Duration | Start Time | Stop Time | Start Station ID | Start Station Name | Start Station Latitude | Start Station Longitude | End Station ID | End Station Name | End Station Latitude | End Station Longitude | Bike ID | User Type | Birth Year | Gender | hour | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 328 | 2016-10-01 00:00:07 | 2016-10-01 00:05:35 | 471 | Grand St & Havemeyer St | 40.712868 | -73.956981 | 3077 | Stagg St & Union Ave | 40.708771 | -73.950953 | 25254 | Subscriber | 1992.0 | 1 | 0 |
1 | 398 | 2016-10-01 00:00:11 | 2016-10-01 00:06:49 | 3147 | E 85 St & 3 Ave | 40.778012 | -73.954071 | 3140 | 1 Ave & E 78 St | 40.771404 | -73.953517 | 17810 | Subscriber | 1988.0 | 2 | 0 |
2 | 430 | 2016-10-01 00:00:14 | 2016-10-01 00:07:25 | 345 | W 13 St & 6 Ave | 40.736494 | -73.997044 | 470 | W 20 St & 8 Ave | 40.743453 | -74.000040 | 20940 | Subscriber | 1965.0 | 1 | 0 |
3 | 351 | 2016-10-01 00:00:21 | 2016-10-01 00:06:12 | 3307 | West End Ave & W 94 St | 40.794165 | -73.974124 | 3357 | W 106 St & Amsterdam Ave | 40.800836 | -73.966449 | 19086 | Subscriber | 1993.0 | 1 | 0 |
4 | 2693 | 2016-10-01 00:00:21 | 2016-10-01 00:45:15 | 3428 | 8 Ave & W 16 St | 40.740983 | -74.001702 | 3323 | W 106 St & Central Park West | 40.798186 | -73.960591 | 26502 | Subscriber | 1991.0 | 1 | 0 |
We'll write a function that does the following:
def get_trip_counts_by_hour(selected_hour):
# make a DataFrame with locations for each bike station
locations = bike_data.groupby("Start Station ID").first()
locations = locations.loc[:, ["Start Station Latitude",
"Start Station Longitude",
"Start Station Name"]]
#select one time of day
subset = bike_data[bike_data["hour"]==selected_hour]
# count trips for each destination
departure_counts = subset.groupby("Start Station ID").count()
departure_counts = departure_counts.iloc[:,[0]]
departure_counts.columns= ["Departure Count"]
# count trips for each origin
arrival_counts = subset.groupby("End Station ID").count().iloc[:,[0]]
arrival_counts.columns= ["Arrival Count"]
#join departure counts, arrival counts, and locations
trip_counts = departure_counts.join(locations).join(arrival_counts)
return trip_counts
# print a sample to check our code works
get_trip_counts_by_hour(6).head()
Departure Count | Start Station Latitude | Start Station Longitude | Start Station Name | Arrival Count | |
---|---|---|---|---|---|
Start Station ID | |||||
72 | 42 | 40.767272 | -73.993929 | W 52 St & 11 Ave | 96.0 |
79 | 29 | 40.719116 | -74.006667 | Franklin St & W Broadway | 79.0 |
82 | 31 | 40.711174 | -74.000165 | St James Pl & Pearl St | 13.0 |
83 | 32 | 40.683826 | -73.976323 | Atlantic Ave & Fort Greene Pl | 35.0 |
116 | 64 | 40.741776 | -74.001497 | W 17 St & 8 Ave | 85.0 |
Now we'll write a function that generates a new folium map and adds circle markers for each station.
def plot_station_counts(trip_counts):
# generate a new map
folium_map = folium.Map(location=[40.738, -73.98],
zoom_start=13,
tiles="CartoDB dark_matter",
width='50%')
# for each row in the data, add a cicle marker
for index, row in trip_counts.iterrows():
# calculate net departures
net_departures = (row["Departure Count"]-row["Arrival Count"])
# generate the popup message that is shown on click.
popup_text = "{}<br> total departures: {}<br> total arrivals: {}<br> net departures: {}"
popup_text = popup_text.format(row["Start Station Name"],
row["Arrival Count"],
row["Departure Count"],
net_departures)
# radius of circles
radius = net_departures/20
# choose the color of the marker
if net_departures>0:
# color="#FFCE00" # orange
# color="#007849" # green
color="#E37222" # tangerine
else:
# color="#0375B4" # blue
# color="#FFCE00" # yellow
color="#0A8A9F" # teal
# add marker to the map
folium.CircleMarker(location=(row["Start Station Latitude"],
row["Start Station Longitude"]),
radius=radius,
color=color,
popup=popup_text,
fill=True).add_to(folium_map)
return folium_map
We'll make 2 maps to show the different patterns for bike migration at 9 am and 6pm.
# plot net departures at 9AM
trip_counts = get_trip_counts_by_hour(9)
plot_station_counts(trip_counts)
# plot net departures at 6PM
trip_counts = get_trip_counts_by_hour(18)
folium_map = plot_station_counts(trip_counts)
folium_map
folium_map.save("part_1.html")