<jupyter_start><jupyter_text>CITYBIKE KATOWICE 2018  You will find below the complete step by step data analysis of the data set from bike provider in Katowice in 2018<jupyter_code>from IPython.display import HTML
HTML('<img src="https://media.giphy.com/media/FUtOLh4CmsXZe/giphy.gif">')<jupyter_output><empty_output><jupyter_text>First things first Import the dataset, review it, add new columns so your work would be easier.<jupyter_code>#this will be needed
import pandas as pd
import numpy as np
import datetime
#import dataset
wyp2018 = pd.read_csv('./dane/wyp_2018.csv')
#give it a glimpse
wyp2018.head(5)
# check its size
wyp2018.shape
#and data types
wyp2018.dtypes
#create additional columns dividing departure time into smaller chunks
wyp2018['start_day'] = pd.DatetimeIndex(wyp2018['start_time']).day
wyp2018['start_month'] = pd.DatetimeIndex(wyp2018['start_time']).month
wyp2018['start_hour'] = pd.DatetimeIndex(wyp2018['start_time']).hour
wyp2018['start_minute'] = pd.DatetimeIndex(wyp2018['start_time']).minute
wyp2018['month_day'] = pd.DatetimeIndex(wyp2018['start_time']).date
wyp2018['duration_min'] = wyp2018['duration_sec']/60
wyp2018['duration_hour'] = (wyp2018['duration_min']/60).apply(int)

#create additional columns to gather more information. Which day of week was it? monday = 0, sunday = 6
wyp2018['which_day'] = pd.DatetimeIndex(wyp2018['start_time']).dayofweek

# Which day of year was it?
wyp2018['daynumber'] = pd.DatetimeIndex(wyp2018['start_time']).dayofyear

#was it weekend?
wyp2018['is_weekend'] = wyp2018['which_day'].apply(lambda x: 1 if (x == 6 or x == 5 ) else 0 )

#was it a holiday?
free = [ datetime.date(2018,1,1),
        datetime.date(2018,1,6),
        datetime.date(2018,4,1),
        datetime.date(2018,4,2),
        datetime.date(2018,5,1),
        datetime.date(2018,5,3),
        datetime.date(2018,5,20),
        datetime.date(2018,5,31),
        datetime.date(2018,8,15),
        datetime.date(2018,11,1),
        datetime.date(2018,11,11),
        datetime.date(2018,11,12),
        datetime.date(2018,12,25),
        datetime.date(2018,12,26)
        ]

wyp2018['is_free'] = wyp2018['month_day'].apply(lambda x: 1 if (x in free) else 0 )


#was it a shopping sunday?
handl = [datetime.date(2018,3,25),
        datetime.date(2018,4,29),
        datetime.date(2018,5,27),
        datetime.date(2018,6,24),
        datetime.date(2018,7,29),
        datetime.date(2018,8,26),
        datetime.date(2018,9,30),
        datetime.date(2018,10,28),
        datetime.date(2018,11,25),
        datetime.date(2018,12,16),
        datetime.date(2018,12,23)
        ]

def conditions(s):
    if (s['month_day'] in handl):
        return 1
    elif (s['month_day'] not in handl) and (s['which_day'] == 6):
        return 0
    else:
        return 2
    
wyp2018['shop'] = wyp2018.apply(conditions, axis=1)

#create additional column to keep the route information in one place (departure - return)
wyp2018["route"] = wyp2018["departure"] + ' - ' + wyp2018["return"]<jupyter_output><empty_output><jupyter_text>Remove the data that is not necessary.<jupyter_code>#What do we know for sure?
print('Bikes were available for rent for {0} days.'.format(wyp2018['month_day'].nunique()))
print('Bikes were available for rent for {0} months.'.format(wyp2018['start_month'].nunique()))
#That is all we can be sure of. Before we start to look for number of rents, average rent time etc,
#we need to check the data looking for outliers, odd values, anything that looks suspicious.
from IPython.display import HTML
HTML('<img src="https://media.giphy.com/media/NS7gPxeumewkWDOIxi/giphy.gif">')
#Let's start with the time of rentals and see how long are they. Are any of them too short to be true? 
(wyp2018.assign(minutes = lambda _wyp2018: _wyp2018['duration_min'].astype(int))
        .groupby('minutes')
        .count()
        .head(5)
)['bike_num']
#Google Maps states you can ride 400m in 1 minute. I think we can safely assume that if a bike was returned to the
#same station it was rented in less than 3 minutes, user has change his mind or the bike was broken. Let's remove
#from the dataset all the rides that lasted lesss than 3 minutes and have the depart = return.
#It will be 20363 records
remove = wyp2018[(wyp2018['duration_min'] < 3) & (wyp2018['departure'] == wyp2018['return'])].index
wyp2018 = wyp2018.drop(index=remove)
#Now let's check all the rides that lasted less than 3 minutes, but depart is different than return. We got 1777 of them
wyp2018[(wyp2018['duration_min'] < 3) &  (wyp2018['departure'] != wyp2018['return'])].head(3)
#Some of them are reasonable, for example Politechnika Śląska	KTBS – Krasińskiego 14. The distance between those 
#2 stations is 230m. I propose to count distance for every route in the dataset, and than remove all the records
#that are shorter than 3 minutes AND the distance between them is greater that 1200m (1 min = 400m according to Google Maps)
#To calculate distance between the stations we need the geocoordinates,thus we will upload stations dataset
#and merge with wyp2018
stations = pd.read_csv('dane/stacje_2018.csv')
#merge datasets adding geo coordinates to departure station
df_temp = pd.merge(wyp2018, stations, left_on='departure', right_on='name')
#merge datasets adding geo coordinates to return station
wyp2018 = pd.merge(df_temp, stations, left_on='return', right_on='name')
#remove unnecessary columns, rename ambigous
wyp2018 = wyp2018.drop(columns = ['name_x', 'name_y', 'capacity_x', 'capacity_y'])
wyp2018 = wyp2018.rename(columns={'id_x': 'dep_id', 'lat_x': 'dep_lat', 'lon_x' : 'dep_lon', 'id_y' : 'ret_id',
                                  'lat_y' : 'ret_lat', 'lon_y' : 'ret_lon'})
#sort df by 'start_time' column
wyp2018 = wyp2018.sort_values(by=['start_time'])
#for each route, calculate the distance. We only can calculate the distance of a straight line between the departure and
#return points.
from geopy.distance import geodesic
wyp2018['distance'] = (wyp2018[['dep_lat','dep_lon','ret_lat','ret_lon']]
        .apply(lambda x: geodesic( [ x[0],x[1] ], [ x[2],x[3] ] ).km, axis=1))
#find all the records that are shorter than 3 minutes AND the distance between them is greater that 1200m
#there are 186 of them - let's remove them
remove = wyp2018[(wyp2018['duration_min'] < 3) & (wyp2018['distance'] > 1.2)].index
wyp2018 = wyp2018.drop(index=remove)
#we have removed 20549 records, what makes 10,6% of the whole dataset
#Let's then check oddly long rentals by grouping rentals by hours
(wyp2018
         .groupby('duration_hour')['bike_num']
         .count()
)
#the MAJORITY of rentals last less than 1 hour. But there are some REALLY STRANGE ones lasting even more than 24 hours
#How many rentals are more than 3 hours?
wyp2018[wyp2018['duration_hour'] > 3].count().head(1)
#That is merely a 0.1% of whole dataset
(wyp2018[wyp2018['duration_hour'] > 3].count()/wyp2018['duration_hour'].count()).head(1)
#I assumed we can remove all the rentals that lasted more than 3 hours without causing a damage to the results
remove = wyp2018[wyp2018['duration_hour'] > 3].index
wyp2018 = wyp2018.drop(index=remove)
#The dataframe is now of shape:
wyp2018.shape<jupyter_output><empty_output><jupyter_text>Once you have nearly all the data, let's start with basic analysis.<jupyter_code>#Now that the outliers are gone we can start analyzing data, starting with the number of bikes and rentals in total
print('There were {0} bikes around the town.'.format(wyp2018['bike_num'].nunique()))
print('They were rented {0} times in total.'.format(wyp2018['bike_num'].count()))
#Also, the average time of rentals:
wyp2018['duration_min'].mean()
#the median of rentals' time
wyp2018['duration_min'].median()
#If the rental was less than 15 minutes, it was free of charge
print('Number of rentals that were free (less than 15 minutes): ')
wyp2018[wyp2018['duration_min'] < 15]['bike_num'].count()
print('It was {0:.2f} of total'.format(wyp2018[wyp2018['duration_min'] < 15]['bike_num'].count()/(wyp2018['bike_num'].count())))<jupyter_output>It was 0.55 of total<jupyter_text>Now it is time for more specific information - number of rentals per month/day/etc<jupyter_code>#Like the number of rental in each month:
print('Number of rentals per month:')
print(wyp2018.groupby('start_month')['bike_num'].count())
print('Most renatls in: ', (wyp2018
                            .groupby('start_month')['bike_num']
                            .count()
                            .nlargest(1)))
#Like the number of rentals per day of a week:
print('rental number per day of a week: ')
print(wyp2018.groupby('which_day')['bike_num'].count())
print('Most renatls in: ', (wyp2018
                            .groupby('which_day')['bike_num']
                            .count()
                            .nlargest(1)))
#the average rentals' time per week day
print('average rentals time per week day:')
print((wyp2018
       .groupby('which_day')['duration_min']
       .mean()))
#the median of rentals time per week day
print('median of rentals time per week day:')
print((wyp2018
       .groupby('which_day')['duration_min']
       .median()))
#on what day was there the most rentals?
print('Days with most rentals:  ')
(wyp2018
     .groupby('month_day')['bike_num']
     .count()
     .nlargest(5))
print('Most popular routes on 15 August: ')
(wyp2018[wyp2018['month_day'] == datetime.date(2018, 8, 15)]
        .groupby('route')['bike_num']
        .count()
        .nlargest(5))

#On which days during popular months were there the least rentals?
(wyp2018[wyp2018['start_month']
         .isin([5,6,7,8])]
         .groupby('month_day')['bike_num']
         .count().nsmallest(5))
#how many holidays were there?
(wyp2018[wyp2018['is_free'] == 1]
     .groupby('month_day')
     .count()
     .index
     .nunique())
#how many rentals were there?
wyp2018[wyp2018['is_free'] == 1]['bike_num'].count()
#what percent of total is this?
print('It is {0:.2f} of total'.format(wyp2018[wyp2018['is_free'] == 1]['bike_num'].count()/(wyp2018['bike_num'].count())))
#how many rentals were there?
print('Rentals on holidays: ')
(wyp2018[wyp2018['is_free'] == 1]
     .groupby('month_day')['bike_num']
     .count()
     .nlargest(5))
#Let's now compare the averages together
#comparing the number of rentals during working days, weekends and holidays
print('average number of rentals during working days: ',
      wyp2018[wyp2018['is_weekend'] == 0]['bike_num'].count() / wyp2018[wyp2018['which_day'].isin(range(0,5))]['month_day'].nunique())
print('average number of rentals during weekendss: ',
      wyp2018[wyp2018['is_weekend'] == 1]['bike_num'].count() / wyp2018[wyp2018['which_day'].isin([5,6])]['month_day'].nunique())
print('average number of rentals during holidays: ',
      wyp2018[wyp2018['is_free'] == 1]['bike_num'].count() / wyp2018[wyp2018['is_free'] == 1].groupby('month_day').count().index.nunique())
#Let's now compare the average time of rentals together
#comparing the average time of rentals during working days, weekends and holidays
print('average time of rentals during working days: ',
      wyp2018[wyp2018['is_weekend'] == 0]['duration_min'].mean())
print('average time of rentals during weekends: ',
      wyp2018[wyp2018['is_weekend'] == 1]['duration_min'].mean())
print('average time of rentals during holidays: ',
      wyp2018[wyp2018['is_free'] == 1]['duration_min'].mean())
#We can also check what is happening durind the Sundays with shops closed vs Sundays when shopping is possible

#number of sundays you can shop
lh = (wyp2018[wyp2018['shop'] == 1]
      .groupby('month_day')['bike_num']
      .nunique()
      .count())

#number of sundays you canot shop
lnh = (wyp2018[wyp2018['shop'] == 0]
       .groupby('month_day')['bike_num']
       .nunique()
       .count())

print('number of sundays you can shop: ', lh)
print('number of sundays you cannot shop: ',  lnh)

print('number of rentals from sundays you can shop: ', wyp2018[wyp2018['shop'] == 1]['bike_num'].count())
print('number of rentals from sundays you cannot shop: ', wyp2018[wyp2018['shop'] == 0]['bike_num'].count())

print('average number of rentals from sundays you can shop: ', wyp2018[wyp2018['shop'] == 1]['bike_num'].count() / lh)
print('average number of rentals from sundays you cannot shop: ', wyp2018[wyp2018['shop'] == 0]['bike_num'].count() / lnh)

print('average time of rentals from sundays you can shop: ', wyp2018[wyp2018['shop'] == 1]['duration_min'].mean())
print('average time of rentals from sundays you cannot shop: ', wyp2018[wyp2018['shop'] == 0]['duration_min'].mean())<jupyter_output>number of sundays you can shop:  9
number of sundays you cannot shop:  29
number of rentals from sundays you can shop:  3811
number of rentals from sundays you cannot shop:  21112
average number of rentals from sundays you can shop:  423.44444444444446
average number of rentals from sundays you cannot shop:  728.0
average time of rentals from sundays you can shop:  38.641800052479574
average time of rentals from sundays you cannot shop:  48.564160193255255<jupyter_text>ALso, let's see how bikes are rented during the day.<jupyter_code>#number of working days the bikes were rented
lr = (wyp2018[wyp2018['which_day']
              .isin(range(0,5))]['month_day']
              .nunique())
#number of weekend days the bikes were rented
lw = (wyp2018[wyp2018['which_day']
              .isin([5,6])]['month_day']
              .nunique())
#number of holidays the bikes were rented
sw = (wyp2018[wyp2018['is_free'] == 1]
              .groupby('month_day')
              .count()
              .index
              .nunique())

#sum of rentals by hour for working days
a = (wyp2018[wyp2018['is_weekend'] == False]
     .groupby('start_hour')['bike_num']
     .count())
#sum of rentals by hour for weekend days
b = (wyp2018[wyp2018['is_weekend'] == True]
     .groupby('start_hour')['bike_num']
     .count())
#sum of rentals by hour for holidays
s = (wyp2018[wyp2018['is_free'] == True]
     .groupby('start_hour')['bike_num']
     .count())

#average number of rentals by hour for working days
c = a / lr
#average number of rentals by hour for weekend days
d = b / lw
#srednia liczba wypozyczen dla przedzialow godzinowych w  dni świąteczne wolne od pracy
t = s / sw

#average time of rentals by hour for working days
e = wyp2018[wyp2018['is_weekend'] == False].groupby('start_hour')['duration_min'].sum() / a
#average time of rentals by hour for weekend days
f = wyp2018[wyp2018['is_weekend'] == True].groupby('start_hour')['duration_min'].sum() / b
#average time of rentals by hour for holidays
u = wyp2018[wyp2018['is_free'] == True].groupby('start_hour')['duration_min'].sum() / s

hour_data = {'sum working days' : a.values, 'sum weekend' : b.values, 'sum holidays' : s.values,
             'mean working' : c.values, 'mean weekend' : d.values, 'mean holidays' : t.values,
             'mean time working' : e.values, 'mean time weekend' : f.values, 'mean time holidays' : u.values}

hourdf = pd.DataFrame(data=hour_data)
hourdf.head(5)
#which station are popular during which hours?

#popular routes during working days
t = wyp2018[wyp2018['is_weekend'] == False].groupby(['start_hour','route'])['bike_num'].count()
trasy = []
for i in range(0,24):
    trasy.append(t.loc[i].sort_values(ascending=False).index[0])

#popular routes during weekend days
t = wyp2018[wyp2018['is_weekend'] == True].groupby(['start_hour','route'])['bike_num'].count()
trasyw = []
for i in range(0,24):
    trasyw.append(t.loc[i].sort_values(ascending=False).index[0])
    
#popular routes during holidays
t = wyp2018[wyp2018['is_free'] == True].groupby(['start_hour','route'])['bike_num'].count()
trasyh = []
for i in range(0,24):
    trasyh.append(t.loc[i].sort_values(ascending=False).index[0])

trasy_data = {'working_days' : trasy, 'weekends' : trasyw, 'holidays': trasyh}

trasy_data = pd.DataFrame(data=trasy_data)

trasy_data
#we can check the same thing, but exclude the routes where departure = return

#popular routes during working days
t = wyp2018[(wyp2018['is_weekend'] == False) & (wyp2018['departure'] != wyp2018['return'])].groupby(['start_hour','route'])['bike_num'].count()
trasy = []
for i in range(0,24):
    trasy.append(t.loc[i].sort_values(ascending=False).index[0])

#popular routes during weekend days
t = wyp2018[(wyp2018['is_weekend'] == True) & (wyp2018['departure'] != wyp2018['return'])].groupby(['start_hour','route'])['bike_num'].count()
trasyw = []
for i in range(0,24):
    trasyw.append(t.loc[i].sort_values(ascending=False).index[0])
    
#popular routes during holidays
t = wyp2018[(wyp2018['is_free'] == True) & (wyp2018['departure'] != wyp2018['return'])].groupby(['start_hour','route'])['bike_num'].count()
trasyh = []
for i in range(0,24):
    trasyh.append(t.loc[i].sort_values(ascending=False).index[0])

trasy_data = {'working_days' : trasy, 'weekends' : trasyw, 'holidays': trasyh}

trasy_data = pd.DataFrame(data=trasy_data)

trasy_data
#it seemed strange for me that there are not so many rides through parks during the weekends, so let's
#compare saturdays, shopping sundays and not-shopping sundays


#popular routes during saturdays
t = wyp2018[(wyp2018['which_day'] == 5)].groupby(['start_hour','route'])['bike_num'].count()
trasy = []
for i in range(0,24):
    trasy.append(t.loc[i].sort_values(ascending=False).index[0])

#popular routes during sundays shopping
t = wyp2018[(wyp2018['which_day'] == 6) & wyp2018['shop'] == 1].groupby(['start_hour','route'])['bike_num'].count()
trasyw = []
for i in range(0,24):
    trasyw.append(t.loc[i].sort_values(ascending=False).index[0])
    
#popular routes during sundays not shopping
t = wyp2018[(wyp2018['which_day'] == 6) & wyp2018['shop'] == 0].groupby(['start_hour','route'])['bike_num'].count()
trasyn = []
for i in range(0,24):
    trasyn.append(t.loc[i].sort_values(ascending=False).index[0])
    
#popular routes during holidays
t = wyp2018[(wyp2018['is_free'] == True)].groupby(['start_hour','route'])['bike_num'].count()
trasyh = []
for i in range(0,24):
    trasyh.append(t.loc[i].sort_values(ascending=False).index[0])

trasy_data = {'saturdays' : trasy, 'sundays' : trasyw, 'sundays_no_shop' : trasyn, 'holidays': trasyh}

trasy_data = pd.DataFrame(data=trasy_data)

trasy_data<jupyter_output><empty_output><jupyter_text>How about summer holidays? Does students use bikes a lot?<jupyter_code># #Let's see if popular stations varies during summer holidays
# trasy_miesiace = pd.DataFrame()
# for i in range(4,13):
#     t = wyp2018[(wyp2018['start_month'] == i) & (wyp2018['departure'] != wyp2018['return'])].groupby(['start_hour','route'])['bike_num'].count()
#     temp = []
#     for j in range(0,24):
#         temp.append(t.loc[j].sort_values(ascending=False).index[0])
#     trasy_miesiace[i] = temp
#trasy_miesiace

#The above code will show popular stations per hour per month - but I didn't find anything interesting<jupyter_output><empty_output><jupyter_text>Now let's check the stations.<jupyter_code>#find the most popular departure stations
print('Most bikes are rented from: ')
wyp2018.groupby('departure')['bike_num'].count().nlargest(5)
#Does it change througout the year?
stacje_mies_dep = pd.DataFrame()
for i in range(4,13):
    t = wyp2018[wyp2018['start_month'] == i].groupby(['departure'])['bike_num'].count().nlargest(5)
    stacje_mies_dep[i] = t.index
stacje_mies_dep
#find the most popular return stations
print('Bikes are most returned at: ')
wyp2018.groupby('return')['bike_num'].count().nlargest(5)
#Does it change througout the year?
stacje_mies_ret = pd.DataFrame()
for i in range(4,13):
    t = wyp2018[wyp2018['start_month'] == i].groupby(['return'])['bike_num'].count().nlargest(5)
    stacje_mies_ret[i] = t.index
stacje_mies_ret
#Find least popular departure stations:
print('Bikes are least rented at: ')
wyp2018.groupby('departure')['bike_num'].count().nsmallest(5)
#Find the least popular return stations:
print('Bikes are least returned at: ')
wyp2018.groupby('return')['bike_num'].count().nsmallest(5)
#Find most popular routes
print('Most popular routes are: ')
wyp2018.groupby('route')['bike_num'].count().nlargest(5)
#Find most popular routes where departure != return
wyp2018[wyp2018['departure'] != wyp2018['return']].groupby('route')['bike_num'].count().nlargest(5)
#Find least popular routes
print('least popular routes are: ')
wyp2018.groupby('route')['bike_num'].count().nsmallest()<jupyter_output>least popular routes are:<jupyter_text>And the most rented bike<jupyter_code>#find most rented bike
print('ID of most rented bike and number of its rides in a season: ')
wyp2018.groupby('bike_num')['duration_sec'].count().nlargest(1)
#find most rented id
mr_bike_id = wyp2018.groupby('bike_num')['start_time'].count().sort_values(ascending=False).head(1).index[0]
#find all its rides
mr_bike = wyp2018[wyp2018['bike_num'] == mr_bike_id]
#find most busy day
date = mr_bike.groupby('month_day')['bike_num'].count().sort_values(ascending=False).index[0]
#create df for this day
mr_bike_day = mr_bike[mr_bike['month_day'] == date]
#sort by start_time
mr_bike_day = mr_bike_day.sort_values(by=['start_time'])
mr_bike_day.head(2)
#show most rented bike's busiest day on map

fig = plt.figure()

#starting point
plt.scatter(mr_bike_day.iloc[0]['dep_lon'], mr_bike_day.iloc[0]['dep_lat'], color='purple', s=200)
plt.text(mr_bike_day.iloc[0]['dep_lon'], mr_bike_day.iloc[0]['dep_lat'], 'start', fontsize=12)

#finishing point
plt.scatter(mr_bike_day.iloc[-1]['ret_lon'], mr_bike_day.iloc[-1]['ret_lat'], color='purple', s=200)
plt.text(mr_bike_day.iloc[-1]['ret_lon'], mr_bike_day.iloc[-1]['ret_lat'], 'koniec', fontsize=12)

#rides
plt.plot(mr_bike_day['dep_lon'].values, mr_bike_day['dep_lat'].values)
plt.plot(mr_bike_day['ret_lon'].values, mr_bike_day['ret_lat'].values, marker='o')

# if you are using notebook 
mplleaflet.display(fig=fig)
#mplleaflet.show(fig=fig)
#does the busiest bike visit all the stations during te season?
#find all the stations the bike has visited:
a_stations = mr_bike.groupby('departure').count().index.to_list()
b_stations = mr_bike.groupby('return').count().index.to_list()
stats = list(set(a_stations) | set(b_stations))

#find all the stations available
alls = stations['name'].to_list()

#find the difference
not_visited = (list(set(alls) - set(stats)))
not_visited
#how many bikes were  moving daily
lr = wyp2018.groupby(['month_day'])['bike_num'].nunique()
lr_data = {'data' : lr.index, 'bikes_moving' : lr.values}
lrdf = pd.DataFrame(data=lr_data)

#vs how many rentals were there
lw = wyp2018.groupby(['month_day'])['bike_num'].count()
lrdf['number_of_rentals'] = lw.values
lrdf.head(5)

#rentals per bike
lrdf['per_bike'] = lrdf['number_of_rentals'] / lrdf['bikes_moving']
lrdf.head(10)
#it means that:
print('One bike has been rented on average {0} a day'.format(lrdf['per_bike'].mean()))
print('The median of rentals for one bike is equal to {0}'.format(lrdf['per_bike'].median()))
#what was the longest ride?
wyp2018[wyp2018['distance'] == wyp2018['distance'].max()].head(1)<jupyter_output><empty_output><jupyter_text>Let's now focus on stations themselves.<jupyter_code>#the stations 2018 dataset were read earlier, we can inspect it now
stations.head(3)
#We can say that:
print('There were {0} stations in Katowice in 2018.'.format(stations['name'].count()))
#what is the distance between each departure station and city center?
#main square in Katowice: 50°15'34.7"N 19°01'19.6"E
wyp2018['centre_distance'] = wyp2018[['dep_lat','dep_lon']].apply(lambda x: geodesic( [ x[0], x[1] ] , [ 50.258697,19.021618] ).km, axis=1)
#plot stations on a map
import matplotlib.pyplot as plt
import mplleaflet

#Create a new figure.
stat_map = plt.figure(figsize=(20,10))
#plt.figure(figsize=(20,10))

#A scatter plot of *y* vs *x* with varying marker size and/or color.
plt.scatter(stations['lon'], stations['lat'], color='purple', s=50)

#Display a figure.
#plt.show()

#Convert a Matplotlib Figure to a Leaflet map. Embed in IPython notebook.
mplleaflet.display(fig=stat_map)

#Convert a Matplotlib Figure to a Leaflet map. Open in a browser
#mplleaflet.show(fig=stacje_mapa)
#how many bikes depart from and return to each station in summary?
dep = wyp2018.groupby(['departure'])['bike_num'].count()
ret = wyp2018.groupby(['return'])['bike_num'].count()
lats = stations.sort_values(by=['name'])['lat']
lons = stations.sort_values(by=['name'])['lon']
each_stat = pd.DataFrame(index = dep.index, data={ 'how_many_departs' : dep.values, 'how_many_returns' : ret.values,
                                           'lat' : lats.values, 'lon' : lons.values})
each_stat.head(5)
#how many bikes depart from each station monthly?
departures = wyp2018.groupby(['departure','start_month'])['bike_num'].count()
deps_month=pd.DataFrame(departures)
deps_month = deps_month.unstack(level=1)
deps_month.head(5)
#how many bikes return to each station monthly?
returns = wyp2018.groupby(['return','start_month'])['bike_num'].count()
reps_month=pd.DataFrame(returns)
reps_month = reps_month.unstack(level=1)
reps_month.head(5)
#any shortages?
shortage = (deps_month - reps_month)
shortage['avg'] = shortage.mean(axis=1)
shortage[shortage['avg'] < 0].sort_values(by=['avg']).head(5)
#remeber to save your work!
wyp2018.to_csv('./dane/allrentals.csv')
stations.to_csv('./dane/allstations.csv')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14979119060751714, 'fraction_numerical': 0.05649672996611772, 'mean_word_length': 5.103149795623948, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 44, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '307628', 'license': 'MIT', 'n_tokens_mistral': 9851, 'n_tokens_neox': 8692, 'n_words': 2291, 'path': 'citybike/2018_analysis.ipynb', 'repo_name': 'AnjaliRavenly/dw-katowice-project', 'size': '25382'}