0 前言
?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是
?? 大數(shù)據(jù)疫情分析及可視化系統(tǒng)
該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦!
??學(xué)長這里給一個題目綜合評分(每項滿分5分)
- 難度系數(shù):3分
- 工作量:3分
- 創(chuàng)新點:4分
?? 更多資料, 項目分享:
https://gitee.com/dancheng-senior/postgraduate文章來源地址http://www.zghlxwxcb.cn/news/detail-805939.html
2 開發(fā)簡介
學(xué)長從各省累計確診人數(shù)隨時間增長的態(tài)勢以及空間分布隨時間增長的態(tài)勢入手,利用所收集的數(shù)據(jù)將各省累計確診人數(shù)的時空分布用地圖、折線圖、堆疊條形圖的形式呈現(xiàn)出來,從總體態(tài)勢進行大致分析,然后再通過在不同粒度上展示各省疫情相關(guān)的詳細信息,以發(fā)現(xiàn)其在不同時間段影響其態(tài)勢變化的原因(境外輸入、相關(guān)政策頒布等)。
同時還將疫情相關(guān)確診、死亡等數(shù)據(jù)與各省的GDP、受教育程度、城鎮(zhèn)化率、醫(yī)療衛(wèi)生水平進行聯(lián)系,以發(fā)現(xiàn)其與GDP、受教育程度、城鎮(zhèn)化率之間是否存在關(guān)系。
其目標(biāo)用戶是政府等防控機關(guān),通過本系統(tǒng)可以分析疫情時空分布模式、監(jiān)控疫情發(fā)展態(tài)勢、評估疫情防控措施。
3 數(shù)據(jù)集
數(shù)據(jù)源于爬蟲與手動搜集:
weibo.json 新浪微博實時熱搜前50的數(shù)據(jù)
ProvinceData.json 省市疫情詳情
源于中國國家統(tǒng)計局(2018年中國統(tǒng)計年鑒)的數(shù)據(jù)
2020-01-10至2020-02-06數(shù)據(jù)來自國家,各省,武漢市衛(wèi)健委疫情公告,2020-02-07后數(shù)據(jù)從今日頭條接口采集
境外輸入數(shù)據(jù)(手動從網(wǎng)上新聞中搜集)
4 實現(xiàn)技術(shù)
4.1 系統(tǒng)架構(gòu)
4.2 開發(fā)環(huán)境
- 1、Node.js(前端Vue和后端node都依賴該環(huán)境)
- 2、開發(fā)工具:Git,vscode,Hbuilder,pycharm
- 3、開發(fā)語言:Python,HTML+CSS+JavaScript
- 4、重點依賴庫:echarts,bootstrap,jQuery
4.3 疫情地圖
新型冠狀病毒肺炎已經(jīng)開始全球蔓延,形勢越來越嚴(yán)峻,我們除了關(guān)注國內(nèi)發(fā)展疫情發(fā)展,也開始關(guān)注境外疫情的發(fā)展變化。通過地理可視化我們能夠很直觀的看到的各個區(qū)域的疫情嚴(yán)重程度。
4.3.1 填充圖(Choropleth maps)
- 填充圖適合表達區(qū)域之間的差異。
- 填充圖能夠很好的展現(xiàn)形全局差異,細微的差異很難表達。
- 但填充圖的展現(xiàn)效果受區(qū)域面積影響比較大,容易形成誤導(dǎo)
上面的填充圖,我們可以關(guān)注到亞洲,歐洲,美洲三大疫情區(qū)域,但是我們很難關(guān)注到,意大利、韓國的疫情嚴(yán)重程度。
4.3.2 氣泡圖
氣泡圖使用不同大小的圓圈表示區(qū)域上的數(shù)值。它在每個地理坐標(biāo)上顯示一個氣泡,或在每個區(qū)域顯示一個氣泡。
下圖我們以氣泡圖形式進行疫情地圖可視化
通過氣泡圖我們可以很明確的看出世界上疫情比較嚴(yán)重的國家,而且不會受到區(qū)域面積的干擾,歐洲一些面積比較小的國家我們也能夠清晰的識別出來。氣泡圖表達方式缺點在于氣泡過多,過大將會產(chǎn)生遮蓋現(xiàn)在。
氣泡是一種比較好的展現(xiàn)形式,如果使用方式不當(dāng)也會產(chǎn)生干擾,比如數(shù)據(jù)映射方法選擇,顏色色帶選擇都會影響數(shù)據(jù)表達的結(jié)果。
關(guān)鍵代碼:
?
# 作者:丹成學(xué)長 q746876041
import json
import requests
import jsonpath
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
from pyecharts.globals import GeoType,RenderType
# 1.目標(biāo)網(wǎng)站
url=‘https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist’
# 2.請求資源
resp=requests.get(url)
# 3.提取數(shù)據(jù)
# 類型轉(zhuǎn)換 json–>dict
data=json.loads(resp.text)
name = jsonpath.jsonpath(data,“KaTeX parse error: Expected 'EOF', got '#' at position 14: ..name") #? print(name) ……confirm”)
# print(confirm)
data_list = zip(name,confirm)
# print(list(data_list))
# 4.可視化 matplotlib 和 pyecharts
nameMap = {
'Singapore Rep.':'新加坡',
'Dominican Rep.':'多米尼加',
'Palestine':'巴勒斯坦',
'Bahamas':'巴哈馬',
'Timor-Leste':'東帝汶',
'Afghanistan':'阿富汗',
'Guinea-Bissau':'幾內(nèi)亞比紹',
"C?te d'Ivoire":'科特迪瓦',
'Siachen Glacier':'錫亞琴冰川',
"Br. Indian Ocean Ter.":'英屬印度洋領(lǐng)土',
'Angola':'安哥拉',
'Albania':'阿爾巴尼亞',
'United Arab Emirates':'阿聯(lián)酋',
'Argentina':'阿根廷',
'Armenia':'亞美尼亞',
'French Southern and Antarctic Lands':'法屬南半球和南極領(lǐng)地',
'Australia':'澳大利亞',
'Austria':'奧地利',
'Azerbaijan':'阿塞拜疆',
'Burundi':'布隆迪',
'Belgium':'比利時',
'Benin':'貝寧',
'Burkina Faso':'布基納法索',
'Bangladesh':'孟加拉國',
'Bulgaria':'保加利亞',
'The Bahamas':'巴哈馬',
'Bosnia and Herz.':'波斯尼亞和黑塞哥維那',
'Belarus':'白俄羅斯',
'Belize':'伯利茲',
'Bermuda':'百慕大',
'Bolivia':'玻利維亞',
'Brazil':'巴西',
'Brunei':'文萊',
'Bhutan':'不丹',
'Botswana':'博茨瓦納',
'Central African Rep.':'中非',
'Canada':'加拿大',
'Switzerland':'瑞士',
'Chile':'智利',
'China':'中國',
'Ivory Coast':'象牙海岸',
'Cameroon':'喀麥隆',
'Dem. Rep. Congo':'剛果民主共和國',
'Congo':'剛果',
'Colombia':'哥倫比亞',
'Costa Rica':'哥斯達黎加',
'Cuba':'古巴',
'N. Cyprus':'北塞浦路斯',
'Cyprus':'塞浦路斯',
'Czech Rep.':'捷克',
'Germany':'德國',
'Djibouti':'吉布提',
'Denmark':'丹麥',
'Algeria':'阿爾及利亞',
'Ecuador':'厄瓜多爾',
'Egypt':'埃及',
'Eritrea':'厄立特里亞',
'Spain':'西班牙',
'Estonia':'愛沙尼亞',
'Ethiopia':'埃塞俄比亞',
'Finland':'芬蘭',
'Fiji':'斐',
'Falkland Islands':'??颂m群島',
'France':'法國',
'Gabon':'加蓬',
'United Kingdom':'英國',
'Georgia':'格魯吉亞',
'Ghana':'加納',
'Guinea':'幾內(nèi)亞',
'Gambia':'岡比亞',
'Guinea Bissau':'幾內(nèi)亞比紹',
'Eq. Guinea':'赤道幾內(nèi)亞',
'Greece':'希臘',
'Greenland':'格陵蘭',
'Guatemala':'危地馬拉',
'French Guiana':'法屬圭亞那',
'Guyana':'圭亞那',
'Honduras':'洪都拉斯',
'Croatia':'克羅地亞',
'Haiti':'海地',
'Hungary':'匈牙利',
'Indonesia':'印度尼西亞',
'India':'印度',
'Ireland':'愛爾蘭',
'Iran':'伊朗',
'Iraq':'伊拉克',
'Iceland':'冰島',
'Israel':'以色列',
'Italy':'意大利',
'Jamaica':'牙買加',
'Jordan':'約旦',
'Japan':'日本',
'Japan':'日本本土',
'Kazakhstan':'哈薩克斯坦',
'Kenya':'肯尼亞',
'Kyrgyzstan':'吉爾吉斯斯坦',
'Cambodia':'柬埔寨',
'Korea':'韓國',
'Kosovo':'科索沃',
'Kuwait':'科威特',
'Lao PDR':'老撾',
'Lebanon':'黎巴嫩',
'Liberia':'利比里亞',
'Libya':'利比亞',
'Sri Lanka':'斯里蘭卡',
'Lesotho':'萊索托',
'Lithuania':'立陶宛',
'Luxembourg':'盧森堡',
'Latvia':'拉脫維亞',
'Morocco':'摩洛哥',
'Moldova':'摩爾多瓦',
'Madagascar':'馬達加斯加',
'Mexico':'墨西哥',
'Macedonia':'馬其頓',
'Mali':'馬里',
'Myanmar':'緬甸',
'Montenegro':'黑山',
'Mongolia':'蒙古',
'Mozambique':'莫桑比克',
'Mauritania':'毛里塔尼亞',
'Malawi':'馬拉維',
'Malaysia':'馬來西亞',
'Namibia':'納米比亞',
'New Caledonia':'新喀里多尼亞',
'Niger':'尼日爾',
'Nigeria':'尼日利亞',
'Nicaragua':'尼加拉瓜',
'Netherlands':'荷蘭',
'Norway':'挪威',
'Nepal':'尼泊爾',
'New Zealand':'新西蘭',
'Oman':'阿曼',
'Pakistan':'巴基斯坦',
'Panama':'巴拿馬',
'Peru':'秘魯',
'Philippines':'菲律賓',
'Papua New Guinea':'巴布亞新幾內(nèi)亞',
'Poland':'波蘭',
'Puerto Rico':'波多黎各',
'Dem. Rep. Korea':'朝鮮',
'Portugal':'葡萄牙',
'Paraguay':'巴拉圭',
'Qatar':'卡塔爾',
'Romania':'羅馬尼亞',
'Russia':'俄羅斯',
'Rwanda':'盧旺達',
'W. Sahara':'西撒哈拉',
'Saudi Arabia':'沙特阿拉伯',
'Sudan':'蘇丹',
'S. Sudan':'南蘇丹',
'Senegal':'塞內(nèi)加爾',
'Solomon Is.':'所羅門群島',
'Sierra Leone':'塞拉利昂',
'El Salvador':'薩爾瓦多',
'Somaliland':'索馬里蘭',
'Somalia':'索馬里',
'Serbia':'塞爾維亞',
'Suriname':'蘇里南',
'Slovakia':'斯洛伐克',
'Slovenia':'斯洛文尼亞',
'Sweden':'瑞典',
'Swaziland':'斯威士蘭',
'Syria':'敘利亞',
'Chad':'乍得',
'Togo':'多哥',
'Thailand':'泰國',
'Tajikistan':'塔吉克斯坦',
'Turkmenistan':'土庫曼斯坦',
'East Timor':'東帝汶',
'Trinidad and Tobago':'特里尼達和多巴哥',
'Tunisia':'突尼斯',
'Turkey':'土耳其',
'Tanzania':'坦桑尼亞',
'Uganda':'烏干達',
'Ukraine':'烏克蘭',
'Uruguay':'烏拉圭',
'United States':'美國',
'Uzbekistan':'烏茲別克斯坦',
'Venezuela':'委內(nèi)瑞拉',
'Vietnam':'越南',
'Vanuatu':'瓦努阿圖',
'West Bank':'西岸',
'Yemen':'也門',
'South Africa':'南非',
'Zambia':'贊比亞',
'Zimbabwe':'津巴布韋'
}
map = Map().add(series_name='世界疫情分布',
data_pair=data_list,
maptype='world',
name_map=nameMap,
is_map_symbol_show=False
)
map.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
map.render('世界疫情分布情況3.html')
# 作者:丹成學(xué)長 q746876041
4.4 全國疫情實時追蹤
全國疫情實時追蹤頁面,支持折線圖、條形圖、扇形圖、地圖熱力圖展示,圖表由Echarts實現(xiàn),支持左上角側(cè)邊欄跳轉(zhuǎn)。
4.6 其他頁面
5 關(guān)鍵代碼
兩個數(shù)據(jù)表
CREATE TABLE `history` (
`ds` datetime NOT NULL COMMENT '日期',
`confirm` int(11) DEFAULT NULL COMMENT '累計確診',
`confirm_add` int(11) DEFAULT NULL COMMENT '當(dāng)日新增確診',
`suspect` int(11) DEFAULT NULL COMMENT '剩余疑似',
`suspect_add` int(11) DEFAULT NULL COMMENT '當(dāng)日新增疑似',
`heal` int(11) DEFAULT NULL COMMENT '累計治愈',
`heal_add` int(11) DEFAULT NULL COMMENT '當(dāng)日新增治愈',
`dead` int(11) DEFAULT NULL COMMENT '累計死亡',
`dead_add` int(11) DEFAULT NULL COMMENT '當(dāng)日新增死亡',
PRIMARY KEY (`ds`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `details` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`update_time` datetime DEFAULT NULL COMMENT '數(shù)據(jù)最后更新時間',
`province` varchar(50) DEFAULT NULL COMMENT '省',
`city` varchar(50) DEFAULT NULL COMMENT '市',
`confirm` int(11) DEFAULT NULL COMMENT '累計確診',
`confirm_add` int(11) DEFAULT NULL COMMENT '新增治愈',
`heal` int(11) DEFAULT NULL COMMENT '累計治愈',
`dead` int(11) DEFAULT NULL COMMENT '累計死亡',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
import requests
import json
import time
import pymysql
#返回歷史數(shù)據(jù)和當(dāng)日詳細數(shù)據(jù)
def get_tencent_data():
url1 = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5"
url2 = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_other"
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36'
}
r1 = requests.get(url1, headers)
r2 = requests.get(url2, headers)
#json字符串轉(zhuǎn)字典
res1 = json.loads(r1.text)
res2 = json.loads(r2.text)
data_all1 = json.loads(res1["data"])
data_all2 = json.loads(res2["data"])
#歷史數(shù)據(jù)
history = {}
for i in data_all2["chinaDayList"]:
ds = "2020." + i["date"]
tup = time.strptime(ds, "%Y.%m.%d") # 匹配時間
ds = time.strftime("%Y-%m-%d", tup) #改變時間輸入格式,不然插入數(shù)據(jù)庫會報錯,數(shù)據(jù)庫是datatime格式
confirm = i["confirm"]
suspect = i["suspect"]
heal = i["heal"]
dead = i["dead"]
history[ds] = {"confirm": confirm, "suspect": suspect, "heal": heal, "dead": dead}
for i in data_all2["chinaDayAddList"]:
ds = "2020." + i["date"]
tup = time.strptime(ds, "%Y.%m.%d") # 匹配時間
ds = time.strftime("%Y-%m-%d", tup) #改變時間輸入格式,不然插入數(shù)據(jù)庫會報錯,數(shù)據(jù)庫是datatime格式
confirm = i["confirm"]
suspect = i["suspect"]
heal = i["heal"]
dead = i["dead"]
history[ds].update({"confirm_add": confirm, "suspect_add": suspect, "heal_add": heal, "dead_add": dead})
#當(dāng)日詳細數(shù)據(jù)
details = []
update_time = data_all1["lastUpdateTime"]
data_country = data_all1["areaTree"] #list 25個國家
data_province = data_country[0]["children"] #中國各省
for pro_infos in data_province:
province = pro_infos["name"] #省名
for city_infos in pro_infos["children"]:
city = city_infos["name"]
confirm = city_infos["total"]["confirm"]
confirm_add = city_infos["today"]["confirm"]
heal = city_infos["total"]["heal"]
dead = city_infos["total"]["dead"]
details.append([update_time, province, city, confirm, confirm_add, heal, dead])
return history, details
def get_conn():
#建立連接
conn = pymysql.connect(host="127.0.0.1", user="root", password="*", db="cov", charset="utf8")
#創(chuàng)建游標(biāo)
cursor = conn.cursor()
return conn,cursor
def close_conn(conn,cursor):
if cursor:
cursor.close()
if conn:
conn.close()
#插入details數(shù)據(jù)
def update_details():
cursor = None
conn = None
try:
li = get_tencent_data()[1] #0是歷史數(shù)據(jù),1是當(dāng)日詳細數(shù)據(jù)
conn,cursor = get_conn()
sql = "insert into details(update_time,province,city,confirm,confirm_add,heal,dead) values(%s,%s,%s,%s,%s,%s,%s)"
sql_query = "select %s=(select update_time from details order by id desc limit 1)" #對比當(dāng)前最大時間戳
#對比當(dāng)前最大時間戳
cursor.execute(sql_query,li[0][0])
if not cursor.fetchone()[0]:
print(f"{time.asctime()}開始更新數(shù)據(jù)")
for item in li:
cursor.execute(sql,item)
conn.commit()
print(f"{time.asctime()}更新到最新數(shù)據(jù)")
else:
print(f"{time.asctime()}已是最新數(shù)據(jù)!")
except:
traceback.print_exc()
finally:
close_conn(conn,cursor)
#插入history數(shù)據(jù)
def insert_history():
cursor = None
conn = None
try:
dic = get_tencent_data()[0]#0代表歷史數(shù)據(jù)字典
print(f"{time.asctime()}開始插入歷史數(shù)據(jù)")
conn,cursor = get_conn()
sql = "insert into history values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
for k,v in dic.items():
cursor.execute(sql,[k, v.get("confirm"),v.get("confirm_add"),v.get("suspect"),
v.get("suspect_add"),v.get("heal"),v.get("heal_add"),
v.get("dead"),v.get("dead_add")])
conn.commit()
print(f"{time.asctime()}插入歷史數(shù)據(jù)完畢")
except:
traceback.print_exc()
finally:
close_conn(conn,cursor)
#更新歷史數(shù)據(jù)
def update_history():
cursor = None
conn = None
try:
dic = get_tencent_data()[0]#0代表歷史數(shù)據(jù)字典
print(f"{time.asctime()}開始更新歷史數(shù)據(jù)")
conn,cursor = get_conn()
sql = "insert into history values (%s,%s,%s,%s,%s,%s,%s,%s,%s)"
sql_query = "select confirm from history where ds=%s"
for k,v in dic.items():
if not cursor.execute(sql_query,k):
cursor.execute(sql,[k, v.get("confirm"),v.get("confirm_add"),v.get("suspect"),
v.get("suspect_add"),v.get("heal"),v.get("heal_add"),
v.get("dead"),v.get("dead_add")])
conn.commit()
print(f"{time.asctime()}歷史數(shù)據(jù)更新完畢")
except:
traceback.print_exc()
finally:
close_conn(conn,cursor)
insert_history()
update_details()
最后
?? 更多資料, 項目分享:文章來源:http://www.zghlxwxcb.cn/news/detail-805939.html
https://gitee.com/dancheng-senior/postgraduate
到了這里,關(guān)于競賽保研 大數(shù)據(jù)疫情分析及可視化系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!