import pandas as pd
import os
from mapboxgl.utils import *
from mapboxgl.viz import *
from mapboxgl.utils import create_color_stops, df_to_geojson
from mapboxgl.viz import CircleViz
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.cluster.vq import kmeans2, whiten
import pandas as pd
# Load Data Set
year = "2020"
month = "08"
URL = f"https://data.urbansharing.com/oslobysykkel.no/trips/v1/{year}/{month}.csv"
o_df = pd.read_csv(URL)
#Matbox token
token = "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw"
o_df.head()
#Converting dates to datetime
o_df["started_at"]= pd.to_datetime(o_df["started_at"])
o_df["ended_at"]= pd.to_datetime(o_df["ended_at"])
o_df['Ukedag'] = o_df['started_at'].dt.day_name()
# Not needed for current program
# df = o_df[["started_at","Ukedag","start_station_id","end_station_id"]]
# df = df.rename(columns={"start_station_id":"sId","end_station_id":"eId"})
# df.head()
o_df.head()
#A class to keep station data
class station:
def __init__(self, id,longitude,latitude,name, change = 0, zone = 0):
self.id = id
self.long = longitude
self.lat = latitude
self.name = name
self.change = change
self.zone = zone
def updateChange(self, tick):
self.change += tick
def setZone(self, zone):
self.zone = zone
def getZone(self):
return self.zone
def getId(self):
return self.id
def getName(self):
return self.name
def getLongLat(self):
return [self.long,self.lat]
def getChange(self):
return self.change
def export(self):
return [self.id,self.name,self.long,self.lat,self.change,self.zone]
#Getting only uniqe station ID's
o_df = o_df.sort_values('start_station_id', ascending=False)
sdf = o_df.drop_duplicates(subset='start_station_name', keep='first')
sdf = sdf.sort_values('start_station_id', ascending=True)
sdf.head()
#Assign each station to it¨s own station object
listOfStations=[]
for index, row in sdf.iterrows():
#id,latitude,longitude
tmp = station(row[3],row[6],row[7],row[4])
listOfStations.append(tmp)
#Devide the stations to zones, based on kmeans2
cor = []
for station in listOfStations:
cor.append(station.getLongLat())
coordinates= np.array(cor)
x, y = kmeans2(whiten(coordinates), 12, iter = 50)
#y is the var with zones
#Plot the zones
sns.set(rc={'figure.figsize':(15,10)})
sns.scatterplot(data=coordinates, x=coordinates[:,0], y=coordinates[:,1], hue=y, palette="deep")
plt.title("Stations clustered by kmeans", fontsize=20)
plt.xlabel('Latitude', fontsize=12)
plt.ylabel('Longitude', fontsize=12)
#Add zones to station object
for i in range(len(listOfStations)):
listOfStations[i].setZone(y[i])
#Count trips from and to every station
#THIS ALG IS SLOW, CAN IT BE REWRITTEN???
for index, row in o_df.iterrows():
sId = row[3]
eId = row[8]
for s in listOfStations:
if s.getId() == sId:
s.updateChange(-1)
sId=False
if s.getId() == eId:
s.updateChange(1)
eId=False
if not sId and not eId:
break
# Create a new df to easier convert it to geojson
newDf = pd.DataFrame(columns = ["Id", "Name", "Longitude", "Latitude", "Change", "Zone"])
newDf.head()
#Fill newDf with data
for s in listOfStations:
series = pd.Series(s.export(), index = newDf.columns)
newDf = newDf.append(series, ignore_index=True)
#Create a geojson object for mapbox plot
df_to_geojson(newDf, filename='points.geojson',
properties=['Id', 'Name','Change','Zone'],
lon='Latitude', lat='Longitude', precision=3)
#For html version
geoFile = "https://raw.githubusercontent.com/buzzCraft/MapBox-RadiusPlot/main/points.geojson"
#For local usage:
#geoFile ='points.geojson'
#Plot the change of bikes for each station
center =(10.77837,59.928349)
zoom = 10
# Generate data breaks and color stops from colorBrewer
color_breaks = [-2000,-1000,-100,-10, 0,10,100,1000,2000]
color_stops = create_color_stops(color_breaks, colors='Spectral')
# Create the viz from the dataframe
viz = CircleViz(geoFile,
access_token=token,
height='500px',
radius=3,
color_property = "Change",
color_stops = color_stops,
center = center,
zoom = zoom,
below_layer = 'waterway-label'
)
viz.show()

#Plot clustered zones on the map
center =(10.77837,59.928349)
zoom = 10
# Generate data breaks and color stops from colorBrewer
color_breaks = [1,2,3,4,5,6,7,8,9,10,11,12]
color_stops = create_color_stops(color_breaks, colors='Set3')
# Create the viz from the dataframe
viz = CircleViz(geoFile,
access_token=token,
height='500px',
radius=3,
color_property = "Zone",
color_stops = color_stops,
center = center,
zoom = zoom,
below_layer = 'waterway-label'
)
viz.show()

# Create a clustered circle map
color_stops = create_color_stops([1, 5, 10, 15], colors='YlOrBr')
viz4 = ClusteredCircleViz(geoFile,
access_token=token,
color_stops=color_stops,
stroke_color='black',
radius_stops=[[1, 5], [10, 10], [50, 15], [100, 20]],
radius_default=2,
cluster_maxzoom=250,
cluster_radius=30,
label_size=12,
opacity=0.9,
center=center,
zoom=zoom)
viz4.show()

#Heatmap, dont make too much sense
heatmap_color_stops = create_color_stops([0.01, 0.25, 0.5, 0.75, 1], colors='RdPu')
heatmap_radius_stops = [[0, 2], [1, 40]] # increase radius with zoom
color_breaks = [round(newDf["Change"].quantile(q=x*0.1), 2) for x in range(2, 10)]
color_stops = create_color_stops(color_breaks, colors='Spectral')
heatmap_weight_stops = create_weight_stops(color_breaks)
# Create the heatmap
viz3 = HeatmapViz(geoFile,
access_token=token,
weight_property="Change",
weight_stops=heatmap_weight_stops,
color_stops=heatmap_color_stops,
radius_stops=heatmap_radius_stops,
opacity=0.8,
center=center,
height='600px',
zoom=zoom,
below_layer='waterway-label')
viz3.show()

# #another change plot
# # Generate data breaks and color stops from colorBrewer
# measure_color = 'Change'
# color_breaks = [round(newDf[measure_color].quantile(q=x*0.1), 2) for x in range(2, 10)]
# color_stops = create_color_stops(color_breaks, colors='Set3')
# # Generate radius breaks from data domain and circle-radius range
# measure_radius = 'Change' #For testing
# radius_breaks = [round(newDf[measure_radius].quantile(q=x*0.1), 2) for x in range(2, 10)]
# radius_stops = create_radius_stops(radius_breaks, 0.5, 20)
# # Create the viz
# viz2 = GraduatedCircleViz(geoFile,
# access_token=token,
# color_property="Change",
# color_stops=color_stops,
# radius_property="Change",
# radius_stops=radius_stops,
# stroke_color='black',
# stroke_width=0.5,
# center=center,
# zoom=zoom,
# opacity=0.75,
# below_layer='waterway-label')
# viz2.show()

from geojson_utils import centroid
newDf.head()
#Example dataset used for training and predicting
sampleDf = pd.DataFrame(columns = ["station_id", "capacity", "bikes_at_station", "timestamp", "status", "Delivered", "data1", "data..n"])
series = pd.Series([1,10,5,"2020-08-01 08:51:09.122000+00:00",0.5,0,"sample","sample"],index = sampleDf.columns)
sampleDf = sampleDf.append(series, ignore_index=True)
series = pd.Series([1,10,6,"2020-08-01 08:54:13.898000+00:00",0.6,1,"sample","sample"],index = sampleDf.columns)
sampleDf = sampleDf.append(series, ignore_index=True)
series = pd.Series([3,16,4,"2020-08-01 08:54:14.878000+00:00",0.25,0,"sample","sample"],index = sampleDf.columns)
sampleDf = sampleDf.append(series, ignore_index=True)
sampleDf.head()