美国共享单车数据分析

  • 一、数据说明
  • 二、数据清洗
    • 1.空值删除
    • 2.数据类型转化
    • 3.统计值概览
    • 4.异常数据
    • 5.数据筛选
    • 6.新增小时、周、月纬度
  • 三、探索性分析
    • 1.数据概览
    • 2.数据异常分析
    • 3.bike_plan与会员关系
    • 4.小时、周、月纬度分析
    • 5.高峰时间骑行数据
    • 6.订阅会员分析
    • 7.工作日与周末出行情况
    • 8.站点热度分析
  • 四、结论

一、数据说明

本次分析的数据是美国旧金山地区共享单车的骑行信息,时间范围2018-01-01至2018-12-23,点击可进行下载csv文件。
数据约180万条,共14个特征。

骑行秒数 开始时间 结束时间 开始站点ID 开始站点名称 开始站点纬度 开始站点经度 结束站点ID 结束站点名称 结束站点纬度 结束站点经度 车辆ID 用户类型 计划参与
duration_sec start_time end_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 bike_share_for_all_trip

本次主要使用Pandas、matplotlib、folium库进行分析与可视化

二、数据清洗

# 导入常用库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import folium   # 地图可视化
from folium.plugins import HeatMap
%matplotlib inline
path = '/Users/valkyrja/Documents/dataanalysis/taobao/2018-baywheels-tripdata.csv'
data = pd.read_csv(path)
data.info(null_counts = True)  #概览数据类型与空值的情况

  • 共1863721行数据
  • 14个特征
  • 开始时间、结束时间数据类型需要调整为datetime
  • 开始结束站点ID、bikeID视情况调整为字符串类型
  • 开始结束站点的ID和名称列,每个特征存在约1万个缺失值
# 进一步观察缺失值情况(每个特征确实11771条数据)
data.isna().sum()#  查看是否有重复数据(无重复数据,无须去重操作)
data.duplicated().sum()


每个特征约1万条确实值,进行删除操作,不影响整体数据。

1.空值删除

#  删除缺失值的行
data.dropna(subset = ['start_station_id', 'start_station_name', 'end_station_id', 'end_station_name'], inplace = True)

2.数据类型转化

#  开始结束时间数据类型调整为datetime类型
for i in ['start_time', 'end_time']:data[i] = pd.to_datetime(data[i])
#  站点id、车辆id调整为字符串类型
for m in ['start_station_id', 'end_station_id', 'bike_id']:data[m] = data[m].astype('int').astype('str')

3.统计值概览

#  对骑行时间进行统计值概览
round(data['duration_sec'].describe(), 2)


这里发现了问题,75%的骑行时间小于870秒(约15分钟),最大值为86366秒(约24个小时),最大时间有点反常。

4.异常数据

#  找数据观察一下
data[data['duration_sec'] > 86300]


  • 根据数据发现,记录时间是没有问题的
  • 但起止站点是一样的,经纬度也相同
  • 推断:车辆故障或用户忘记关闭记录锁
#  查看99%骑行时间大小
num = int(data.shape[0] * 0.99)
data['duration_sec'].sort_values(ascending = True).iloc[:num].tail(10)


99%骑行时间是在5496秒(约1.5小时)以下,根据实际共享单车骑行时间判断,2小时以下为正常骑行的标准,对2小时以上的骑行数据判定为异常数据。

5.数据筛选

#  筛选出2小时及以下骑行时间的数据
data_2 = data[data['duration_sec'] <= 7200]#  简单看一下骑行数据的分布
plt.hist(data_2['duration_sec'], bins = 50)
plt.show()


筛选数据后,约90%数据仍在2000秒(30分钟)以内。

6.新增小时、周、月纬度

data_2['hour'] = data_2['start_time'].dt.hour
data_2['week'] = data_2['start_time'].dt.dayofweek
data_2['week'] = data_2['start_time'].dt.month#    顺便重命名共享计划的列名为 'bike_plan',原名太长了
data.rename(columns = {'bike_share_for_all_trip':'bike_plan'}, inplace = True)

三、探索性分析

1.数据概览

#    共计1838703行数据
data_2.shape
#    共计4852辆共享单车
data_2['bike_id'].nunique()
#    站点共计331个
data_2['start_station_id'].nunique()
data_2['end_station_id'].nunique()
#    订阅会员发生1572041次的骑行记录,普通用户发生266662次骑行记录
data_2['user_type'].value_counts()

订阅会员数量约占85%,普通用户约占15%

#    bike_plan计划用户发生160898次骑行记录。
data_2['bike_plan'].value_counts()
#    骑行时间统计值观察
round(data_2['duration_sec'].describe(), 2)

2.数据异常分析

  1. 车辆故障,当时无法关锁
  2. 用户遗忘关锁
  3. 遗忘关锁,他人接力骑行
  4. 订阅用户故意不关锁
  5. bike_plan用户故意不关锁
#  首先看一下起终点相同的数据
de = data[data['start_station_id'] == data['end_station_id']]
de.shape


起终点相同的数据约5千,车辆在同一个站点在某个时间点开始计时,然后在另外一个时间点关闭计时,是否一开始车辆就未关锁,直到系统自动关锁。

#  查看异常数据与bike_plan的关系
de['bike_plan'].value_counts()


非bike_plan用户占比约83%。

#    异常数据与用户类型的关系
de['user_type'].value_counts()


订阅用户约占55%,普通用户占44%。但是数据相关性并不明显,无法直接判断。

3.bike_plan与会员关系

data_2[data_2['bike_plan'] == 'Yes'].shape

bike_plan的数据约16万条

#    bike_plan为真的情况下,会员的数量
data_2[data_2['bike_plan'] == 'Yes']['user_type'].value_counts()


bike_plan为真,用户为订阅用户,订阅会员骑行记录中bike_plan计划记录约占10%。

4.小时、周、月纬度分析

#    分别按小时、周、月的纬度对骑行时间分组求和
gbhs = data_2.groupby(by = ['hour'], as_index = False).agg({'duration_sec':'sum'})
gbws = data_2.groupby(by = ['week'], as_index = False).agg({'duration_sec':'sum'})
gbms = data_2.groupby(by = ['month'], as_index = False).agg({'duration_sec':'sum'})
#    对求和数据进行可视化
plt.figure(figsize = (18, 6))plt.subplot(131)
h_sec = gbhs['duration_sec'] / 3600
plt.plot(gbhs['hour'], h_sec)
plt.xticks(list(range(0, 24)))
plt.title('hour')plt.subplot(132)
w_sec = gbws['duration_sec'] / 3600
plt.plot(gbws['week'], w_sec)
plt.title('week')
plt.xticks(list(range(0, 7)))plt.subplot(133)
m_sec = gbms['duration_sec'] / 3600
plt.plot(gbms['month'], m_sec)
plt.xticks(list(range(1, 13)))
plt.title('month')plt.show()

  • 小时纬度:凌晨、夜间骑行时间低,白天骑行时间高。
  • 小时纬度:推测早晚上班高峰用户集中使用,7点-9点,17点-19点。
  • 周纬度:工作日使用时常高,周末较低。
  • 月纬度:5月-10月车辆骑行时间高。
    推测工作通勤、天气气温与车辆使用时常有很大的相关性。10月后骑行时间明显降低,推测收入将随之降低,是否可以在这个节点推出优惠的冬季订阅套餐,从而提升冬季较低的收入。
#    分别按小时、周、月的纬度对骑行时间分组求mean
gbhm = data_2.groupby(by = ['hour'], as_index = False).agg({'duration_sec':'mean'})
gbwm = data_2.groupby(by = ['week'], as_index = False).agg({'duration_sec':'mean'})
gbmm = data_2.groupby(by = ['month'], as_index = False).agg({'duration_sec':'mean'})
#    对以上数据进行可视化
plt.figure(figsize = (18, 6))plt.subplot(131)
h_sec = gbhm['duration_sec'] / 3600
plt.plot(gbhm['hour'], h_sec)
plt.xticks(list(range(0, 24)))
plt.title('hour')plt.subplot(132)
w_sec = gbwm['duration_sec'] / 3600
plt.plot(gbwm['week'], w_sec)
plt.title('week')
plt.xticks(list(range(0, 7)))plt.subplot(133)
m_sec = gbmm['duration_sec'] / 3600
plt.plot(gbmm['month'], m_sec)
plt.xticks(list(range(1, 13)))
plt.title('month')plt.show()

  • 小时纬度:7点-9点,17点-18点,车辆平均骑行时间小于20分钟。
  • 周纬度:周一至周五,平均骑行时常小于20分钟,周末在25分钟浮动。
  • 月纬度:5月至9月骑行时间在20分钟以上,8月突出降低。
    推测:车辆平均使用时间在30分钟以内,与通勤距离有关。8月气温较高,骑车感受不佳,车辆骑行时间降低,网上搜索2018年美国7、8月历史最高气温为30度。

5.高峰时间骑行数据

#    通勤高峰车辆使用次数
data_2[data_2['hour'].isin([7, 9, 17, 19])].shape
h_s = data_2[data_2['hour'].isin([7, 9, 17, 19])]['duration_sec'].sum()
all_sum = data_2['duration_sec'].sum()

7-9点, 17-19点期间共发生了约58万次的骑行记录,约占全年骑行记录的32%,骑行时常约占全年的30%

6.订阅会员分析

Sub_sec = data_2[(data_2['hour'].isin([7, 9, 17, 19])) & (data_2['user_type'] == 'Subscriber') & (data_2['bike_plan'] == 'No')]['duration_sec'].sum()

订阅会员年骑行时常为295442648秒,约占全年使用时间的23%。

#    订阅会员与普通用户的骑行时间可视化
C_dur = data_2[data_2['user_type'] == 'Customer']['duration_sec'] / 3600
Su_dur = data_2[data_2['user_type'] == 'Subscriber']['duration_sec'] / 3600plt.hist(C_dur, bins = 50, label = 'C_dur', color = 'r')
plt.hist(Su_dur, bins = 50, label = 'Su_dur', alpha = 0.3, color = 'y')
plt.legend()
plt.show()


订阅用户累计骑行时间远高普通用户,这在用户类别统计中就可推测出。

7.工作日与周末出行情况

#    获取工作日与周末数据
week_da = data_2[data_2['week'].isin([5, 6])]
work_da = data_2[data_2['week'].isin([0, 1, 2, 3, 4])]
#    画了4个图,平日、周末、订阅用户、普通用户的交叉关系
plt.figure(figsize = (20, 10))
#   图1:周末订阅用户、普通用户的骑行时间的分布
plt.subplot(2,2,1)
plt.hist(round(week_da[week_da['user_type'] == 'Subscriber']['duration_sec'] / 3600, 2), bins = 50, label = 'Su',\color = 'r')
plt.hist(round(week_da[week_da['user_type'] == 'Customer']['duration_sec'] / 3600, 2), bins = 50, alpha = 0.5, label = 'Cu',color = 'g')
plt.title('week_day')
plt.legend()#   图2:工作日订阅用户、普通用户的骑行时间的分布
plt.subplot(2,2,2)
plt.hist(round(work_da[work_da['user_type'] == 'Subscriber']['duration_sec'] / 3600, 2), bins = 50, label = 'Su',\color = 'r')
plt.hist(round(work_da[work_da['user_type'] == 'Customer']['duration_sec'] / 3600, 2), bins = 50, alpha = 0.5, label = 'Cu',color = 'g')
plt.title('work_day')
plt.legend()#   图3:订阅用户工作日、周末骑行时间分布
plt.subplot(2,2,3)
plt.hist(round(week_da[week_da['user_type'] == 'Subscriber']['duration_sec'] / 3600, 2), bins = 50, label = 'week',\color = 'r')
plt.hist(round(work_da[work_da['user_type'] == 'Subscriber']['duration_sec'] / 3600, 2), bins = 50, alpha = 0.5, label = 'work',color = 'g')
plt.title('Sub')
plt.legend()#   图4:普通用户工作日、周末骑行时间分布
plt.subplot(2,2,4)
plt.hist(round(week_da[week_da['user_type'] == 'Customer']['duration_sec'] / 3600, 2), bins = 50, label = 'week',\color = 'r')
plt.hist(round(work_da[work_da['user_type'] == 'Customer']['duration_sec'] / 3600, 2), bins = 50, alpha = 0.5, label = 'work',color = 'g')
plt.title('Cu')
plt.legend()plt.show()

  • 工作日、周末订阅用户骑行时间占比高,且骑行时间都是在25分钟以内
  • 对比工作日,订阅用户在周末骑行时间占比较少,小于50%;对比工作日,普通用户周末骑行时间约占工作日骑行时间的50%
    对周末骑行时间较长的普通用户进行进一步分析与用户调研,是否有机会推出周末的低价订阅套餐。

8.站点热度分析

#    最忙的站点分析(出发、结束的前8名)
sss = data_2['start_station_id'].value_counts().sort_values(ascending = False).head(8)
ess = data_2['end_station_id'].value_counts().sort_values(ascending = False).head(8)plt.figure(figsize = (16, 8))
plt.subplot(121)
plt.plot(sss.index, sss.values)
plt.title('start_station')plt.subplot(122)
plt.plot(ess.index, ess.values)
plt.title('end_station')plt.show()

#    起、终点年吞吐前8名
print(round(sss.mean() / 365, 2))
print(round(ess.mean() / 365, 2))

前8名每个站点,平均每天出发93次车,进入106辆车。

这个要结合实际站点情况进行评估,是否有足够的场地,人力进行运营。

#    获取经纬度信息
loc = data_2[['start_station_latitude', 'start_station_longitude', 'end_station_latitude', 'end_station_longitude']]#  查看这些经纬度的区域
plt.figure(figsize = (12, 6))
plt.subplot(1,2,1)
plt.scatter(loc['start_station_latitude'], loc['start_station_longitude'], alpha = 0.3)
plt.title('start')plt.subplot(1,2,2)
plt.scatter(loc['end_station_latitude'], loc['end_station_longitude'], alpha = 0.3)
plt.title('end')plt.show()


观察可知,共享单车主要在这3个区域骑行。

#    分别3个区域的获取经纬度信息
re_a = data_2[data_2['start_station_latitude'] < 37.5]
re_b = data_2[data_2['start_station_longitude'] < -122.45]
re_c = data_2[(data_2['start_station_longitude'] > -122.45) & (data_2['start_station_longitude'] < -122.1)]
#    分别获得3个区域经纬度的平均值
a_la, a_lo = re_a['start_station_latitude'].mean(), re_a['start_station_longitude'].mean()
b_la, b_lo = re_b['start_station_latitude'].mean(), re_b['start_station_longitude'].mean()
c_la, c_lo = re_c['start_station_latitude'].mean(), re_c['start_station_longitude'].mean()
#    绘制3个底图
m_a = folium.Map(location = [a_la, a_lo], zoom_start = 8, control_scale = True)
m_b = folium.Map(location = [a_la, a_lo], zoom_start = 8, control_scale = True)
m_c = folium.Map(location = [a_la, a_lo], zoom_start = 8, control_scale = True)
#    首先分别构造热力图的数据
a_num = re_a.groupby(by = ['start_station_latitude', 'start_station_longitude'], \as_index = False).agg({'start_station_name':'count'})
b_num = re_b.groupby(by = ['start_station_latitude', 'start_station_longitude'], \as_index = False).agg({'start_station_name':'count'})
c_num = re_c.groupby(by = ['start_station_latitude', 'start_station_longitude'], \as_index = False).agg({'start_station_name':'count'})
#    绘制a区域的热力图
HeatMap(a_num).add_to(m_a)
m_a

#    绘制b区域的热力图
HeatMap(b_num).add_to(m_b)
m_b![在这里插入图片描述](https://img-blog.csdnimg.cn/20201101001532714.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZhbGt5cmphMTEw,size_16,color_FFFFFF,t_70#pic_center)

#    绘制c区域的热力图
HeatMap(c_num).add_to(m_c)
m_c

四、结论

  1. 异常骑行数据约1万条,车辆无法关锁,用户遗漏关锁,车辆自动开锁。调查异常数据车辆,并评估是否开放提示用户关锁功能与车辆长时间自动关锁的功能。预计在一定成都上能避免用户使用的不便以及减少车辆的运营成本(锁未关,他人随意骑行)。
  2. 进出站前8的站点,每天进出站平均106、93辆车,需要评估站点是否有足够的空间以及运营人员进行维护。使用次数最多的车辆同样需要进行定期关注维护与保养。
  3. 十月后用户的骑行时常大幅度减少,是否可以在9月提前推出10月-12月的低价畅骑卡,以此提高冬季的收入。
  4. 普通用户在周末的骑行时常约占工作日的50%,需要进行深入分析与用户调研,探索普通用户周末的出行需求,评估是否有必要推出周末畅行卡,最大程度增加收入,因为周末车辆闲置无法产生盈利。

美国旧金山共享单车数据分析相关推荐

  1. sql date类型_共享单车数据分析的SQL数据库设计

    SQL,发音为" sequel"(或SQL,如果愿意的话),是数据科学家的重要工具.实际上,它可以说是获取数据工作中最重要的语言.在共享单车数据分析的SQL设计中,我们将从入门者的 ...

  2. 共享单车数据分析的SQL数据库设计

    SQL,发音为" sequel"(或SQL,如果愿意的话),是数据科学家的重要工具.实际上,它可以说是获取数据工作中最重要的语言.在共享单车数据分析的SQL设计中,我们将从入门者的 ...

  3. 摩拜共享单车数据分析项目报告

    文章目录 项目背景 数据探索 数据挖掘 数据分析 时间维度 空间维度 用户维度 项目背景 随着智能手机的普及和手机用户的激增,共享单车作为城市交通系统的一个重要组成部分,以绿色环保.便捷高效.经济环保 ...

  4. 毕业设计 题目:基于大数据的共享单车数据分析

    文章目录 0 前言 1 项目背景 2 项目分析思维导图 3 项目分析具体步骤 3.1 读取数据 3.2 数据分析 3.1.1 数据预处理--每日使用量分析 3.1.2 连续7天的单日使用分析结论 3. ...

  5. kaggle共享单车数据分析及预测(随机森林)

    文章目录 一.数据收集 1.1.项目说明 1.2.数据内容及变量说明 二.数据处理 2.1.导入数据 2.2.缺失值处理 2.3.Label数据(即count)异常值处理 2.4.其他数据异常值处理 ...

  6. Spark SQL上海摩拜共享单车数据分析

    1 生成DataFrame对象 val bikeDF = sqlContext.read.format("csv").option("header", &quo ...

  7. 美国共享单车数据分析

    分析三大美国城市的自行车共享系统相关的数据:芝加哥.纽约和华盛顿特区.写一个脚本,该脚本会接受原始输入并在终端中创建交互式体验,以展现这些统计信息. 目录 数据集说明: 起始时间分析: 骑行时长分析: ...

  8. 毕业设计 基于大数据的共享单车数据分析与可视化

    文章目录 0 前言 1 课题背景 2 数据清洗 3 数据可视化 热力图 整体特征分布 **查看2011-2012间的单车租借情况** 天气对于租借数量的影响 湿度与温度对于租借数量的影响 注册用户与未 ...

  9. python共享单车数据分析_数据分析_共享单车骑行时间分析-zeropython

    数据分析一共分为五个任务: 第一步:明确分析的任务 分析出每个季度的骑行的平均时长和各个季度的对比 第二步:数据处理 先看数据: shell 查看csv 数据前十行 ➜ data cat bikesh ...

  10. 膜拜共享单车数据分析

    数据:2017年5月两周内,北京40余万辆摩拜单车被30余万摩拜用户的使用情况(该开源数据来源于2017年摩拜算法挑战赛).数据包含300余万条出行记录数据,每条的数据包含了订单号(orderid ) ...

最新文章

  1. 【HeadFirst 设计模式学习笔记】2 观察者模式
  2. 这届不敢看体检报告的年轻人还能“年轻”多久?
  3. 驾驶卡丁车 模拟,迷宫(女赛)
  4. 结对-结对编项目贪吃蛇-设计文档
  5. AcWing 3208. Z字形扫描
  6. centos mate桌面_CENTOS7安装各种桌面系统 CENTOS安装桌面图形化GUI GNOME/KDE/Cinnamon/MATE/Xfce...
  7. 程序员——神圣的职业
  8. 2008生产实习 日程安排
  9. H3C ospf与nat转换
  10. Atitit 浏览器tech原理与概论 目录 1. 浏览器概述 1 1.1. 浏览器野史 UserAgent列传 1 1.2. 浏览器趋势 1 1.3. 浏览器大战 1 1.4. 三次浏览器大战 2
  11. Zemax操作--9(全局坐标设定及使用方法)
  12. 证照之星下载证件照制作软件ps及使用教程,附序列号秘钥激活码
  13. Unity 鼠标点击事件穿透
  14. 电子签名法学习-(1)电子认证服务机构
  15. 归一化MinMaxScaler()、标准化StandardScaler()(特征工程之特征预处理)
  16. Intouch2020与施耐德PLC通讯
  17. python求组合数c(m、n)编程题_c语言编程问题,计算出从n 个不同元素中取出m 个元素(m≤n)的组合数。编写程序...
  18. X87 FPU 指令集
  19. Java包括jvm及API,Java基础(下)(JVM、API)
  20. 商务汇报PPT制作的七堂课-第三课:结构搭建

热门文章

  1. Linux文件|菜鸟教程
  2. 高等数学张宇18讲 第二讲 极限与连续
  3. ps cc 2014 智能切图
  4. caj文件添加endnote_endnote怎么导入caj
  5. word转化为html操作步骤
  6. 如何将iPhone投屏到Mac电脑上?
  7. 小程序在wxml里转数字_微信小程序 之wxml保留小数点后两位数的方法及转化为字符串的方法...
  8. 增长模型—评分卡模型
  9. error Code:410 Error Message:appid and openid not match 威富通技术支持,兴业银行微信支付接入支持
  10. python 读取excel表内容:以获取高铁站点经纬度为例子