日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

【Python Onramp】7. web端可视化:北京地铁数据统计分析实例以及简易Echarts绘图

發(fā)布時(shí)間:2023/12/20 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Python Onramp】7. web端可视化:北京地铁数据统计分析实例以及简易Echarts绘图 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

系列文章目錄

見【Python Onramp】 0. 卷首語(yǔ)

上一篇:【Python Onramp】6.一篇文章了解web開發(fā)要點(diǎn):用Python開發(fā)簡(jiǎn)易的網(wǎng)頁(yè)端成績(jī)查詢系統(tǒng)
下一篇:【Python Onramp】8.Python爬蟲(1)基于requests和BeautifulSoup的全國(guó)區(qū)劃數(shù)據(jù)爬蟲

本文目錄

  • 系列文章目錄
  • 開篇總結(jié)
  • 項(xiàng)目描述
    • task1
    • task2
    • task3
    • task4
  • 要點(diǎn)總覽
    • 要點(diǎn)1:Echarts
    • 要點(diǎn)2:時(shí)間函數(shù)
    • 要點(diǎn)3:pandas.dataframe復(fù)習(xí)
    • 要點(diǎn)4:JavaScript數(shù)據(jù)結(jié)構(gòu):JSON
  • 具體實(shí)現(xiàn)
    • step1:統(tǒng)計(jì)
      • 時(shí)間提取
      • 時(shí)間軸統(tǒng)計(jì)
    • step2:利用jsonify傳遞
    • step3:直接保存為js數(shù)據(jù)實(shí)現(xiàn)

開篇總結(jié)

一個(gè)思想:查找資料!將關(guān)鍵詞百度一下,比如你想得到Echarts的模板,就可以直接百度。由于編程學(xué)習(xí)內(nèi)容非常多樣,查找不僅是方法,更是技能
幾個(gè)要點(diǎn)

  • Echarts
  • 時(shí)間datetime模塊
  • JSON
  • pandas.dataframe的一些知識(shí)復(fù)習(xí)

項(xiàng)目描述

詳見:https://github.com/Honour-Van/CS50/tree/master/Visualization2

這個(gè)項(xiàng)目中你將通過北京地鐵數(shù)據(jù)的展示進(jìn)行

對(duì)地鐵數(shù)據(jù)進(jìn)行分析之后的可視化分析。

數(shù)據(jù)見 data,數(shù)據(jù)是北京地鐵刷卡數(shù)據(jù)。第一行是數(shù)據(jù)標(biāo)題,其含義如下:

  • a) carType:SUB 是唯一取值,表明數(shù)據(jù)是地鐵,本次作業(yè)可以不用;
  • b)icID:交通卡編號(hào),每個(gè)編號(hào)對(duì)應(yīng)一張卡,已經(jīng)消密脫敏;
  • c) cardType:卡類型
  • d) tradeType:交易類型
  • e)UpLine:上車線路編號(hào)
  • f) UpTime:上車時(shí)間
  • g) UpStation:上車站編號(hào)
  • h) DownLine:下車線路編號(hào)
  • i)DownTime:下車時(shí)間
  • j) DownStation:下車站編號(hào)
  • k) State:棄用

壓縮包內(nèi)的 PDF 文檔是地鐵線路編號(hào)和車站編號(hào),供參考。

為便于程序調(diào)試,數(shù)據(jù)中有 Subway_20190301_top100000.txt(實(shí)際上是 Subway_20180301_top100000.txt,誤為 2019),是 Subway_20180301.txt 的前 100000 行數(shù)據(jù),可以用于初步調(diào)試程序,待調(diào)試完畢后再用完整數(shù)據(jù)跑,節(jié)省時(shí)間

task1

計(jì)算乘車耗時(shí)時(shí)段內(nèi)的人數(shù)。每條記錄是一次乘車行為,下車時(shí)間減去上車時(shí)間,即為耗時(shí),題目要求統(tǒng)計(jì)耗時(shí) 10 分鐘有多少人,耗時(shí) 15 分鐘有多少人。以分鐘為單位,計(jì)算出每個(gè)時(shí)間段內(nèi)的人數(shù)。如 1 分鐘:10 人,2 分鐘 20 人,……,10 分鐘 500 人,30 分鐘 5000 人。計(jì)算耗時(shí),用 round()函數(shù)四舍五入到分中。對(duì)下車時(shí)間早于或等于上車時(shí)間的數(shù)據(jù)予以清除,對(duì)超過 120 分鐘的數(shù)據(jù)予以清除,對(duì)于不是 20180301 的數(shù)據(jù)清除。輸出時(shí),按耗時(shí)升序排序輸出到 PeopleInSubwayTime.txt,并在 Excel 中打開該文件,形成條形圖。

task2

所有地鐵內(nèi)人數(shù)時(shí)間分布。以 10 分鐘為間隔,統(tǒng)計(jì)地鐵內(nèi)人數(shù)多少。進(jìn)站相當(dāng)于人數(shù)增加,出站相當(dāng)于人數(shù)減少。以凌晨 00:00 開始計(jì)數(shù),此刻人數(shù)為 0。統(tǒng)計(jì) 00:00-00:09,00:10-00:19,以此類推,要求標(biāo)記為:00:00-00:00,00:10-00:19(以下同)。清除數(shù)據(jù)的規(guī)則與 5 相同。按時(shí)間自然升序輸出到 PeopleInSubwayCount.txt,形成折線圖;

task3

利用兩個(gè)數(shù)據(jù)文件,通過 Python+Flask 模式,將數(shù)據(jù)輸出到網(wǎng)頁(yè),利用 eCharts 顯示出形如 Excel 的統(tǒng)計(jì)圖。每個(gè)統(tǒng)計(jì)圖都支持柱狀圖和折線圖切換;

task4

利用兩個(gè)數(shù)據(jù)文件,通過包含 JS 數(shù)據(jù)文件方式,顯示出形如 Excel 的統(tǒng)計(jì)圖。與 task3 頁(yè)面要求一致,僅數(shù)據(jù)源不同而已。

要點(diǎn)總覽

主要的內(nèi)容包括Flask和JavaScript我們?cè)谥岸家呀?jīng)學(xué)過了,如果你已經(jīng)掌握了,那么這個(gè)項(xiàng)目將會(huì)是一個(gè)非常愉悅的項(xiàng)目。

要點(diǎn)1:Echarts

Echarts是一個(gè)基于 JavaScript 的開源可視化圖表庫(kù),版式精美簡(jiǎn)約,具有可交互性。

之前我們已經(jīng)使用過其Python版Pyecharts,但實(shí)際上,PyEcharts只是Echarts的一個(gè)封裝,自動(dòng)生成對(duì)應(yīng)的JavaScript代碼。我們現(xiàn)在直接動(dòng)手編輯HTML和JavaScript。

在網(wǎng)頁(yè)端,可以直接利用圖形界面生成所需的options對(duì)象,在實(shí)際操作時(shí),只需選取指定對(duì)象進(jìn)行options設(shè)置即可。

<script type="text/javascript">var EChart1 = echarts.init(document.getElementById("stat1"));var EChart2 = echarts.init(document.getElementById("stat2"));var option = {title: { text: "" },tooltip: {},legend: { data: ["折線圖", "柱形圖"] },toolbox: {feature: {magicType: { type: ["line", "bar"] },saveAsImage: {},},},xAxis: { data: [] },yAxis: {},series: [{ name: "折線圖", type: "line", data: [] },{ name: "柱形圖", type: "bar", data: [] },],}; /*設(shè)置統(tǒng)計(jì)圖形參數(shù)*/$.get("/getData1", function (data) {option.title.text = "地鐵乘車用時(shí)統(tǒng)計(jì)";option.xAxis.data = data[0];option.series[0].data = eval("[" + data[1] + "]");option.series[1].data = eval("[" + data[1] + "]");EChart1.setOption(option);});$.get("/getData2", function (data) {option.title.text = "地鐵站內(nèi)人員統(tǒng)計(jì)";option.xAxis.data = data[0];option.series[0].data = eval("[" + data[1] + "]");option.series[1].data = eval("[" + data[1] + "]");EChart2.setOption(option);});</script>

要點(diǎn)2:時(shí)間函數(shù)

datetime 的使用方法:

  • strptime()函數(shù):將datetime對(duì)象轉(zhuǎn)換為指定時(shí)間格式的字符串
  • timedelta類型:用于求時(shí)間差

我們每十分鐘一分組,還需要使用如下兩個(gè)函數(shù),分別為時(shí)間編組和對(duì)應(yīng)組別時(shí)間的格式化輸出。

def time_group(etime: datetime.time) -> int:return etime.hour * 6 + (etime.minute // 10)def group2time(group_num: int) -> str:hour = group_num // 6dec_min = group_num % 6return str(hour).rjust(2, '0') + ":" + str(dec_min * 10).rjust(2, '0') + '-' + str(hour).rjust(2, '0') + ":" + str(dec_min * 10 + 9).rjust(2, '0')

要點(diǎn)3:pandas.dataframe復(fù)習(xí)

導(dǎo)出行列數(shù)以表示進(jìn)度:https://blog.csdn.net/lwgkzl/article/details/80988126

dataframe 更名:https://blog.csdn.net/weixin_43745169/article/details/89306686

dataframe 定位:https://blog.csdn.net/W_weiying/article/details/81411257

另外,不會(huì)把 python 列表直接變成 js 中的變量,從而使用了復(fù)制粘貼。

要點(diǎn)4:JavaScript數(shù)據(jù)結(jié)構(gòu):JSON

https://www.runoob.com/json/json-tutorial.html
JSON是JavaScript的內(nèi)置數(shù)據(jù)結(jié)構(gòu),也通用于各種編程語(yǔ)言中,在flask端的數(shù)據(jù)傳遞過程中,我們可以利用jsonify函數(shù)將dataframe編碼為JSON,隨后傳到網(wǎng)頁(yè)端進(jìn)行顯示。這樣的程序,數(shù)據(jù)不在網(wǎng)頁(yè)端顯示,保密等級(jí)上升一層。
詳細(xì)可以自行搜索用法。

具體實(shí)現(xiàn)

step1:統(tǒng)計(jì)

時(shí)間提取

不正則數(shù)據(jù):

  • 下車早于上車
  • 消除不在當(dāng)日的數(shù)據(jù)
  • 清除前后超過 120 分鐘的數(shù)據(jù)

返回上車和下車時(shí)間即可,上述的工作可以交由具體實(shí)現(xiàn)時(shí)。

第二次決定加入時(shí)間差作為第三個(gè)返回值

from datetime import datetime, time import pandas as pd from mytool import progress_bar, time_group, group2time# filename = "test/test.txt" # filename = "data/Subway_20190301_Top100000.txt" filename = "data/Subway_20180301.txt"df = pd.read_csv(filename) res = {}pb = progress_bar(df.shape[0], 100)for _, line in df.iterrows():starttime = datetime.strptime(str(line["UpTime"]), "%Y%m%d%H%M%S")endtime = datetime.strptime(str(line["DownTime"]), "%Y%m%d%H%M%S")if starttime.day != 1 or endtime.day != 1:continuedelta = endtime - starttimeif delta.days < 0:continueif delta.seconds > 7200:continuetg = time_group(starttime)res[tg] = res.get(tg, 0) + 1tg = time_group(endtime)res[tg] = res.get(tg, 0) - 1pb.progress(_)for i in range(143):res[i+1] = res.get(i+1, 0) + res.get(i, 0)res = sorted(res.items(), key=lambda x: x[0]) res = [(group2time(x[0]),x[1]) for x in res] pd.DataFrame(res, columns=['時(shí)間組', '人數(shù)']).to_csv("./out/PeopleInSubwayCount.csv",index=False)

其中,mytool是自己實(shí)現(xiàn)的幾個(gè)組件,包括時(shí)間處理以及進(jìn)度條組件:

from datetime import datetimeclass progress_bar():def __init__(self, workload, length) -> None:self._workload = workloadself.stage_d = int(workload/length)self.stage_c = 0self.stage_n = 0self.length = lengthdef progress(self, cur):if cur > self.stage_c:self.stage_c += self.stage_dself.stage_n += 1print('\r' + "[" + (self.stage_n *'o').ljust(self.length) + "]" + "loading...", end='')def time_group(etime: datetime.time) -> int:return etime.hour * 6 + (etime.minute // 10)def group2time(group_num: int) -> str:hour = group_num // 6dec_min = group_num % 6return str(hour).rjust(2, '0') + ":" + str(dec_min * 10).rjust(2, '0') + '-' + str(hour).rjust(2, '0') + ":" + str(dec_min * 10 + 9).rjust(2, '0')

時(shí)間軸統(tǒng)計(jì)

如果記錄的進(jìn)入離開時(shí)間在特定范圍內(nèi),記增減。注意,每次要做部分和,保證當(dāng)前是之前所有進(jìn)站出站數(shù)據(jù)的綜合結(jié)果。

from datetime import datetime import pandas as pd from mytool import progress_bar# filename = "data/Subway_20190301_top100000.txt" filename = "data/Subway_20180301.txt" res = {} df = pd.read_csv(filename)pb = progress_bar(df.shape[0], 100)for _, line in df.iterrows():starttime = datetime.strptime(str(line["UpTime"]), "%Y%m%d%H%M%S")endtime = datetime.strptime(str(line["DownTime"]), "%Y%m%d%H%M%S")if starttime.day != 1 or endtime.day != 1:continuedelta = endtime - starttimeif delta.days < 0:continueif delta.seconds > 7200:continueminutes = round(delta.seconds / 60)res[minutes] = res.get(minutes, 0) + 1pb.progress(_)res = sorted(res.items(), key=lambda x: x[0]) pd.DataFrame(res, columns=['耗時(shí)(分鐘)', '人數(shù)']).to_csv("./out/PeopleInSubwayTime.csv", index=False)

step2:利用jsonify傳遞

from flask import Flask, jsonify # 新增代碼。裝入Flask import pandas as pdapp = Flask(__name__) # 新增代碼@app.route("/") # 新增代碼,對(duì)應(yīng)執(zhí)行root()函數(shù) def root():return app.send_static_file("visual.html")@app.route("/getData1") def getData1():df = pd.read_csv("./out/PeopleInSubwayTime.csv")data = [df.iloc[:, 0].tolist(), df.iloc[:, 1].tolist()]print(data)return jsonify(data)@app.route("/getData2") def getData2():df = pd.read_csv("./out/PeopleInSubwayCount.csv")data = [df.iloc[:, 0].tolist(), df.iloc[:, 1].tolist()]print(data)return jsonify(data)if __name__ == "__main__":app.run(host="0.0.0.0", port=80, debug=True) # eof <!DOCTYPE html> <html><head><meta charset="utf-8" /><title>ECharts</title><script src="/static/echarts.min.js"></script><script src="/static/jquery-3.6.0.min.js"></script><!--引入自定義的數(shù)據(jù)--></head><body><div id="stat1" style="width: 600px; height: 400px"></div><div id="stat2" style="width: 600px; height: 400px"></div><!--統(tǒng)計(jì)圖顯示于此--><script type="text/javascript">var EChart1 = echarts.init(document.getElementById("stat1"));var EChart2 = echarts.init(document.getElementById("stat2"));var option = {title: { text: "" },tooltip: {},legend: { data: ["折線圖", "柱形圖"] },toolbox: {feature: {magicType: { type: ["line", "bar"] },saveAsImage: {},},},xAxis: { data: [] },yAxis: {},series: [{ name: "折線圖", type: "line", data: [] },{ name: "柱形圖", type: "bar", data: [] },],}; /*設(shè)置統(tǒng)計(jì)圖形參數(shù)*/$.get("/getData1", function (data) {option.title.text = "地鐵乘車用時(shí)統(tǒng)計(jì)";option.xAxis.data = data[0];option.series[0].data = eval("[" + data[1] + "]");option.series[1].data = eval("[" + data[1] + "]");EChart1.setOption(option);});$.get("/getData2", function (data) {option.title.text = "地鐵站內(nèi)人員統(tǒng)計(jì)";option.xAxis.data = data[0];option.series[0].data = eval("[" + data[1] + "]");option.series[1].data = eval("[" + data[1] + "]");EChart2.setOption(option);});</script></body> </html>

step3:直接保存為js數(shù)據(jù)實(shí)現(xiàn)

這樣的話,flask端需要做的工作就很少了

from flask import Flask, jsonify # 新增代碼。裝入Flask import pandas as pdapp = Flask(__name__) # 新增代碼@app.route("/") # 新增代碼,對(duì)應(yīng)執(zhí)行root()函數(shù) def root():return app.send_static_file("visjs.html")if __name__ == "__main__":app.run(host="0.0.0.0", port=80, debug=True) # eof

js端需要稍微多加一點(diǎn)數(shù)據(jù)重組的操作:

<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>ECharts</title><script src="./static/echarts.min.js"></script><script src="./static/myData.js"></script></head><body><div id="stat1" style="width: 600px; height: 400px"></div><div id="stat2" style="width: 600px; height: 400px"></div><!--統(tǒng)計(jì)圖顯示于此--><script type="text/javascript">var EChart1 = echarts.init(document.getElementById("stat1"));var EChart2 = echarts.init(document.getElementById("stat2"));var option = {title: { text: "" },tooltip: {},legend: { data: ["折線圖", "柱形圖"] },toolbox: {feature: {magicType: { type: ["line", "bar"] },saveAsImage: {},},},xAxis: { data: [] },yAxis: {},series: [{ name: "折線圖", type: "line", data: [] },{ name: "柱形圖", type: "bar", data: [] },],}; /*設(shè)置統(tǒng)計(jì)圖形參數(shù)*/option.title.text = "地鐵乘車用時(shí)統(tǒng)計(jì)";option.xAxis.data = userData1[0];option.series[0].data = userData1[1];option.series[1].data = userData1[1];EChart1.setOption(option);option.title.text = "地鐵站內(nèi)人員統(tǒng)計(jì)";option.xAxis.data = userData2[0];option.series[0].data = userData2[1];option.series[1].data = userData2[1];EChart2.setOption(option);</script></body> </html>

總結(jié)

以上是生活随笔為你收集整理的【Python Onramp】7. web端可视化:北京地铁数据统计分析实例以及简易Echarts绘图的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。