> 技术文档 > 实验七:数据可视化交互

实验七:数据可视化交互


数据可视化交互

实验目的
1. 了解数据可视化的一般原则
2. 掌握数据可视化的分类
3. 掌握数据可视化的常见技术
4. 本次实验是对全国的空气质量进行可视化分析并进行数
据统计技术对比
实验原理
设计可视化系统或选择交互方式的时候,除了能够完成任
务本身之外,还要遵循一些基本的原则。例如,交互的延时性
需要在用户可以接受的范围之内,并有效控制用户交互的成
本。这些基本原则对交互的效果起着至关重要的作用富。
另外,交互的技术有很多种,本次实验是对文本进行可视
化生成词云图片与传统的统计技术对比。
交互的原则、交互的分类以及常见的交互技术,尤其是几
种常见的交互技术,只有熟练掌握并使用恰当,才可能设计出
用户体验良好的可视化应用。尽管交互的技术有很多种,但交互
技术本身并无优劣之分,选择哪种交互技术的依据是具体的场
景和应用需求。
实验环境
Python:v3.6
【实验步骤】
一、安装 pyecharts
pip install pyecharts
实验七:数据可视化交互
二、下载数据
下载数据文件(data.txt),该文件表示了一些城市某天的空
气质量指数(AQI),请完成如下实验。
实验七:数据可视化交互
三、实验任务
实验 1:AQI 横向对比条形图
任务:使用 Pyecharts 绘制各城市 AQI 值的横向条形图,要求:
1. 按 AQI 从高到低排序
2. 添加全局配置项:标题为“城市 AQI 对比”,坐标轴名称分别
为“AQI 指数”和“城市” 3. 使 MarkLine 标记 AQI 均值线(参考值:80),并设置不同
颜色区分高于/低于均值的城市

from pyecharts.charts import Barfrom pyecharts import options as opts# 甘肃省各城市AQI数据(示例数据)city_aqi = { \"兰州\": 125, \"天水\": 92, \"白银\": 78, \"金昌\": 65, \"嘉峪关\": 88, \"武威\": 73, \"张掖\": 68, \"平凉\": 85, \"酒泉\": 70, \"庆阳\": 95, \"定西\": 82, \"陇南\": 60, \"临夏\": 75, \"甘南\": 55}# 按AQI值从高到低排序sorted_cities = sorted(city_aqi.items(), key=lambda x: x[1], reverse=True)cities = [city[0] for city in sorted_cities]aqi_values = [city[1] for city in sorted_cities]# 计算颜色列表(高于均值红色,低于均值绿色)colors = [\"#c23531\" if aqi >= 80 else \"#61a0a8\" for aqi in aqi_values]# 创建横向条形图bar = ( Bar() .add_xaxis(cities) .add_yaxis( series_name=\"AQI指数\", y_axis=aqi_values, label_opts=opts.LabelOpts(position=\"right\", formatter=\"{c}\"), itemstyle_opts=opts.ItemStyleOpts(color=colors), ) .reversal_axis() # 转换为横向条形图 .set_series_opts( markline_opts=opts.MarkLineOpts( data=[opts.MarkLineItem(y=80, name=\"均值线\")], # 修正这里:将 \'type\' 改为 \'type_\' linestyle_opts=opts.LineStyleOpts(color=\"#fc8452\", width=2, type_=\"dashed\"), label_opts=opts.LabelOpts(position=\"middle\", formatter=\"均值: 80\"), ) ) .set_global_opts( title_opts=opts.TitleOpts(title=\"城市 AQI 对比\"), xaxis_opts=opts.AxisOpts(name=\"AQI 指数\"), yaxis_opts=opts.AxisOpts(name=\"城市\"), visualmap_opts=opts.VisualMapOpts( is_show=False, # 不显示视觉映射组件 dimension=0, range_color=[\"#61a0a8\", \"#c23531\"], # 颜色范围 range_size=10, pieces=[{\"gte\": 80, \"color\": \"#c23531\"}, {\"lt\": 80, \"color\": \"#61a0a8\"}] ), tooltip_opts=opts.TooltipOpts(trigger=\"axis\", axis_pointer_type=\"shadow\") ))# 渲染图表到HTML文件bar.render(\"gansu_aqi_comparison.html\")

实验七:数据可视化交互

实验 2:AQI 等级分布饼图
任务:基于 AQI 等级划分(优/良/轻度污染/中度污染/重度污
染),绘制饼图并添加交互功能:
1. 使用 Pie 图表展示各等级下城市数量占比
2. 标签显示百分比和等级名称,突出显示占比最大的扇区
3. 添加点击事件:单击扇区时弹出该等级详细城市数量及城市
名称列表

from pyecharts.charts import Piefrom pyecharts import options as optsfrom pyecharts.commons.utils import JsCode# 示例数据 - 甘肃省各城市AQI值city_aqi = { \"兰州\": 125, \"天水\": 92, \"白银\": 78, \"金昌\": 65, \"嘉峪关\": 88, \"武威\": 73, \"张掖\": 68, \"平凉\": 85, \"酒泉\": 70, \"庆阳\": 95, \"定西\": 82, \"陇南\": 60, \"临夏\": 75, \"甘南\": 55}# 定义AQI等级标准aqi_levels = { \"优\": (0, 50), \"良\": (51, 100), \"轻度污染\": (101, 150), \"中度污染\": (151, 200), \"重度污染\": (201, 300)}# 统计各等级城市数量level_count = {level: 0 for level in aqi_levels}level_cities = {level: [] for level in aqi_levels}for city, aqi in city_aqi.items(): for level, (low, high) in aqi_levels.items(): if low <= aqi <= high: level_count[level] += 1 level_cities[level].append(city) break# 准备饼图数据data = []for level, count in level_count.items(): if count > 0: # 添加城市列表作为额外数据 data.append((level, count, \", \".join(level_cities[level])))# 按数量排序(从大到小)data.sort(key=lambda x: x[1], reverse=True)# 找出占比最大的等级(用于突出显示)max_level = data[0][0]# 创建饼图pie = ( Pie() .add( series_name=\"AQI等级分布\", data_pair=[(d[0], d[1]) for d in data], radius=[\"30%\", \"70%\"], center=[\"50%\", \"50%\"], rosetype=\"radius\", label_opts=opts.LabelOpts( formatter=\"{b}: {d}%\", # 显示等级名称和百分比 font_size=14 ), # 添加额外数据(城市列表) encode={\"itemName\": 0, \"value\": 1, \"tooltip\": 2} ) .set_global_opts( title_opts=opts.TitleOpts(title=\"甘肃省AQI等级分布\"), legend_opts=opts.LegendOpts( orient=\"vertical\", pos_left=\"left\" ), tooltip_opts=opts.TooltipOpts( formatter=\"{b}: {c}个城市
{a}: {d}%\"
, trigger=\"item\" ) ) .set_series_opts( # 简化突出显示效果 emphasis_opts=opts.EmphasisOpts(), # 设置初始高亮(最大占比扇区) selected_mode=\"single\", selected_offset=20 ))# 添加点击事件处理函数js_code = \"\"\"function(params) { if (params.componentType === \'series\' && params.seriesType === \'pie\') { // 获取点击的等级名称 var level = params.name; // 获取城市列表(从额外数据中) var cities = params.data.tooltip; // 创建弹窗内容 var content = \'
\'; content += \'等级: \' + level + \'
\'; content += \'城市数量: \' + params.value + \'
\'; content += \'城市列表: \' + cities; content += \'
\'; // 创建弹窗 var popup = document.createElement(\'div\'); popup.style.cssText = \'position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); \' + \'background:#fff; padding:20px; border:2px solid #ccc; \' + \'border-radius:8px; box-shadow:0 0 20px rgba(0,0,0,0.2); z-index:9999; \' + \'min-width:300px; max-width:500px;\'; popup.innerHTML = content; // 添加关闭按钮 var closeBtn = document.createElement(\'button\'); closeBtn.innerText = \'关闭\'; closeBtn.style.cssText = \'display:block; margin:10px auto 0; padding:6px 20px; \' + \'background:#eee; border:1px solid #ccc; border-radius:4px; cursor:pointer;\'; closeBtn.onclick = function() { document.body.removeChild(popup); }; popup.appendChild(closeBtn); document.body.appendChild(popup); }}\"\"\"
# 设置图表初始化选项和事件监听pie.add_js_funcs(f\"\"\"chart.on(\'click\', {js_code});\"\"\")# 渲染图表pie.render(\"aqi_level_distribution.html\")# 打印数据统计结果(用于调试)print(\"AQI等级分布统计:\")for level, count in level_count.items(): if count > 0: print(f\"{level}: {count}个城市 - {\', \'.join(level_cities[level])}\")

实验七:数据可视化交互
实验七:数据可视化交互

实验 3:多城市 AQI 对比仪表盘
任务:使用 Tab 或 Page 组件构建多图表仪表盘:
1. 第一选项卡:显示 AQI 前 10 城市的横向条形图
2. 第二选项卡:展示西北地区城市 AQI 散点数据(添加回归
线)与东部城市 AQI 散点数据(添加回归线)的对比
3. 第三选项卡:组合折线图(各地区 AQI 指数的变化)
4. 要求所有图表共享主题风格(如 ThemeType.DARK)

from pyecharts import options as optsfrom pyecharts.charts import Bar, Scatter, Line, Tab, Gridfrom pyecharts.globals import ThemeTypefrom pyecharts.commons.utils import JsCodeimport numpy as npfrom sklearn.linear_model import LinearRegression# 数据整理(与原代码一致)data = [ \"海门\", 9, \"鄂尔多斯\", 12, \"招远\", 12, \"舟山\", 12, \"齐齐哈尔\", 14, \"盐城\", 15, \"赤峰\", 16, \"青岛\", 18, \"乳山\", 18, \"金昌\", 19, \"泉州\", 21, \"莱西\", 21, \"日照\", 21, \"胶南\", 22, \"南通\", 23, \"拉萨\", 140, \"云浮\", 24, \"梅州\", 25, \"文登\", 25, \"上海\", 25, \"攀枝花\", 25, \"威海\", 25, \"承德\", 25, \"厦门\", 26, \"汕尾\", 26, \"潮州\", 26, \"丹东\", 27, \"太仓\", 27, \"曲靖\", 27, \"烟台\", 28, \"福州\", 29, \"瓦房店\", 30, \"即墨\", 30, \"抚顺\", 31, \"玉溪\", 31, \"张家口\", 31, \"阳泉\", 31, \"莱州\", 32, \"湖州\", 32, \"汕头\", 32, \"昆山\", 33, \"宁波\", 33, \"湛江\", 33, \"揭阳\", 34, \"荣成\", 34, \"连云港\", 35, \"葫芦岛\", 35, \"常熟\", 36, \"东莞\", 36, \"河源\", 36, \"淮安\", 36, \"泰州\", 36, \"南宁\", 37, \"营口\", 37, \"惠州\", 37, \"江阴\", 37, \"蓬莱\", 37, \"韶关\", 38, \"嘉峪关\", 38, \"广州\", 38, \"延安\", 38, \"太原\", 39, \"清远\", 39, \"中山\", 39, \"昆明\", 39, \"寿光\", 40, \"盘锦\", 40, \"长治\", 41, \"深圳\", 41, \"珠海\", 42, \"宿迁\", 43, \"咸阳\", 43, \"铜川\", 44, \"平度\", 44, \"佛山\", 44, \"海口\", 44, \"江门\", 45, \"章丘\", 45, \"肇庆\", 46, \"大连\", 47, \"临汾\", 47, \"吴江\", 47, \"石嘴山\", 49, \"沈阳\", 50, \"苏州\", 50, \"茂名\", 50, \"嘉兴\", 51, \"长春\", 51, \"胶州\", 52, \"银川\", 52, \"张家港\", 52, \"三门峡\", 53, \"锦州\", 54, \"南昌\", 54, \"柳州\", 54, \"三亚\", 54, \"自贡\", 56, \"吉林\", 56, \"阳江\", 57, \"泸州\", 57, \"西宁\", 57, \"宜宾\", 58, \"呼和浩特\", 58, \"成都\", 58, \"大同\", 58, \"镇江\", 59, \"桂林\", 59, \"张家界\", 59, \"宜兴\", 59, \"北海\", 60, \"西安\", 61, \"金坛\", 62, \"东营\", 62, \"牡丹江\", 63, \"遵义\", 63, \"绍兴\", 63, \"扬州\", 64, \"常州\", 64, \"潍坊\", 65, \"重庆\", 66, \"台州\", 67, \"南京\", 67, \"滨州\", 70, \"贵阳\", 71, \"无锡\", 71, \"本溪\", 71, \"克拉玛依\", 72, \"渭南\", 72, \"马鞍山\", 72, \"宝鸡\", 72, \"焦作\", 75, \"句容\", 75, \"北京\", 79, \"徐州\", 79, \"衡水\", 80, \"包头\", 80, \"绵阳\", 80, \"乌鲁木齐\", 84, \"枣庄\", 84, \"杭州\", 84, \"淄博\", 85, \"鞍山\", 86, \"溧阳\", 86, \"库尔勒\", 86, \"安阳\", 90, \"开封\", 90, \"济南\", 92, \"德阳\", 93, \"温州\", 95, \"九江\", 96, \"邯郸\", 98, \"临安\", 99, \"兰州\", 99, \"沧州\", 100, \"临沂\", 103, \"南充\", 104, \"天津\", 105, \"富阳\", 106, \"泰安\", 112, \"诸暨\", 112, \"郑州\", 113, \"哈尔滨\", 114, \"聊城\", 116, \"芜湖\", 117, \"唐山\", 119, \"平顶山\", 119, \"邢台\", 119, \"德州\", 120, \"济宁\", 120, \"荆州\", 127, \"宜昌\", 130, \"义乌\", 132, \"丽水\", 133, \"洛阳\", 134, \"秦皇岛\", 136, \"株洲\", 143, \"石家庄\", 147, \"莱芜\", 148, \"常德\", 152, \"保定\", 153, \"湘潭\", 154, \"金华\", 157, \"岳阳\", 169, \"长沙\", 175, \"衢州\", 177, \"廊坊\", 193, \"菏泽\", 194, \"合肥\", 229, \"武汉\", 273, \"大庆\", 279]cities = []aqi_values = []for i in range(0, len(data), 2): cities.append(data[i]) aqi_values.append(data[i+1])northwest_cities = [\"西安\", \"兰州\", \"西宁\", \"银川\", \"乌鲁木齐\", \"克拉玛依\", \"库尔勒\"]east_cities = [\"上海\", \"南京\", \"杭州\", \"宁波\", \"苏州\", \"无锡\", \"常州\", \"南通\", \"扬州\", \"镇江\", \"泰州\", \"嘉兴\", \"绍兴\"]# 创建Tab组件(移除init_opts,改为在add时指定主题)tab = Tab() # pyecharts 1.x中Tab初始化不接受init_opts,主题通过add时的init_opts传递## 选项卡1:AQI前10城市横向条形图(添加init_opts到Bar的初始化中)sorted_data = sorted(zip(cities, aqi_values), key=lambda x: x[1], reverse=True)top10_cities = [x[0] for x in sorted_data[:10]]top10_aqi = [x[1] for x in sorted_data[:10]]bar = ( Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK)) # 在图表初始化时指定主题 .add_xaxis(top10_cities) .add_yaxis(\"AQI指数\", top10_aqi, category_gap=\"50%\") .reversal_axis() .set_global_opts( title_opts=opts.TitleOpts(title=\"AQI前10城市\"), xaxis_opts=opts.AxisOpts(name=\"AQI值\"), yaxis_opts=opts.AxisOpts(name=\"城市\"), visualmap_opts=opts.VisualMapOpts( min_=min(top10_aqi), max_=max(top10_aqi), dimension=0, is_piecewise=True, pos_top=\"50\", pos_left=\"0\", range_color=[\"#2f4554\", \"#c23531\"], ), ) .set_series_opts( label_opts=opts.LabelOpts(position=\"right\"), markline_opts=opts.MarkLineOpts( data=[opts.MarkLineItem(type_=\"average\", name=\"平均值\")] ) ))tab.add(bar, \"AQI前10城市\")## 选项卡2:西北与东部城市AQI对比散点图(图表初始化时指定主题)# 西北城市数据nw_aqi = [aqi_values[cities.index(city)] for city in northwest_cities if city in cities]nw_x = np.arange(len(nw_aqi)).reshape(-1, 1)nw_reg = LinearRegression().fit(nw_x, nw_aqi)nw_line = nw_reg.predict(nw_x).tolist()# 东部城市数据east_aqi = [aqi_values[cities.index(city)] for city in east_cities if city in cities]east_x = np.arange(len(east_aqi)).reshape(-1, 1)east_reg = LinearRegression().fit(east_x, east_aqi)east_line = east_reg.predict(east_x).tolist()scatter = ( Scatter(init_opts=opts.InitOpts(theme=ThemeType.DARK)) # 添加主题配置 .add_xaxis(northwest_cities) .add_yaxis( \"西北城市AQI\", nw_aqi, symbol_size=10, label_opts=opts.LabelOpts(is_show=False), ) .add_xaxis(east_cities) .add_yaxis( \"东部城市AQI\", east_aqi, symbol_size=10, label_opts=opts.LabelOpts(is_show=False), ) .set_global_opts( title_opts=opts.TitleOpts(title=\"西北与东部城市AQI对比\"), xaxis_opts=opts.AxisOpts(name=\"城市\"), yaxis_opts=opts.AxisOpts(name=\"AQI值\"), tooltip_opts=opts.TooltipOpts( formatter=JsCode( \"function(params){return params.seriesName + \'
\' + params.name + \': \' + params.value[1];}\"
) ), ) .set_series_opts( markline_opts=[ opts.MarkLineOpts( data=[opts.MarkLineItem(type_=\"average\", name=\"西北平均值\")], linestyle_opts=opts.LineStyleOpts(width=2, color=\"#61a0a8\"), ), opts.MarkLineOpts( data=[opts.MarkLineItem(type_=\"average\", name=\"东部平均值\")], linestyle_opts=opts.LineStyleOpts(width=2, color=\"#d48265\"), ), ] ))# 添加回归线line = ( Line(init_opts=opts.InitOpts(theme=ThemeType.DARK)) # 添加主题配置 .add_xaxis(northwest_cities) .add_yaxis( \"西北回归线\", nw_line, is_smooth=True, linestyle_opts=opts.LineStyleOpts(width=4, color=\"#61a0a8\"), label_opts=opts.LabelOpts(is_show=False), ) .add_xaxis(east_cities) .add_yaxis( \"东部回归线\", east_line, is_smooth=True, linestyle_opts=opts.LineStyleOpts(width=4, color=\"#d48265\"), label_opts=opts.LabelOpts(is_show=False), ))# 使用Grid组合散点图和折线图grid = ( Grid() .add(scatter, grid_opts=opts.GridOpts(pos_left=\"5%\", pos_right=\"20%\")) .add(line, grid_opts=opts.GridOpts(pos_left=\"5%\", pos_right=\"20%\")))tab.add(grid, \"西北与东部城市对比\")## 选项卡3:各地区AQI变化折线图(图表初始化时指定主题)regions = { # ... 地区城市列表 ...}region_data = {}for region, city_list in regions.items(): aqis = [] for city in city_list: if city in cities: aqis.append(aqi_values[cities.index(city)]) if aqis: region_data[region] = sum(aqis) / len(aqis)sorted_regions = sorted(region_data.items(), key=lambda x: x[1], reverse=True)region_names = [x[0] for x in sorted_regions]region_aqis = [x[1] for x in sorted_regions]line_chart = ( Line(init_opts=opts.InitOpts(theme=ThemeType.DARK)) # 添加主题配置 .add_xaxis(region_names) .add_yaxis( \"平均AQI\", region_aqis, is_smooth=True, symbol=\"circle\", symbol_size=10, linestyle_opts=opts.LineStyleOpts(width=3), label_opts=opts.LabelOpts(is_show=True), markpoint_opts=opts.MarkPointOpts( data=[ opts.MarkPointItem(type_=\"max\", name=\"最大值\"), opts.MarkPointItem(type_=\"min\", name=\"最小值\"), ] ), markline_opts=opts.MarkLineOpts( data=[opts.MarkLineItem(type_=\"average\", name=\"平均值\")] ), ) .set_global_opts( title_opts=opts.TitleOpts(title=\"各地区平均AQI对比\"), xaxis_opts=opts.AxisOpts(name=\"地区\", axislabel_opts=opts.LabelOpts(rotate=30)), yaxis_opts=opts.AxisOpts(name=\"平均AQI值\"), tooltip_opts=opts.TooltipOpts(trigger=\"axis\"), ))tab.add(line_chart, \"各地区AQI对比\")# 渲染图表tab.render(\"aqi_dashboard.html\")

实验七:数据可视化交互
实验七:数据可视化交互
实验七:数据可视化交互

实验 4:2D 地理 AQI 可视化
任务:结合 Geo 实现二维地理可视化:
1. 在中国地图上标记城市位置,使用不同颜色表示 AQI 值
2. 展示不同地区 AQI 数值

from pyecharts import options as optsfrom pyecharts.charts import Geofrom pyecharts.globals import ChartType, SymbolType# 数据准备(保持原始数据不变)data = [ \"海门\", 9, \"鄂尔多斯\", 12, \"招远\", 12, \"舟山\", 12, \"齐齐哈尔\", 14, \"盐城\", 15, \"赤峰\", 16, \"青岛\", 18, \"乳山\", 18, \"金昌\", 19, \"泉州\", 21, \"莱西\", 21, \"日照\", 21, \"胶南\", 22, \"南通\", 23, \"拉萨\", 140, \"云浮\", 24, \"梅州\", 25, \"文登\", 25, \"上海\", 25, \"攀枝花\", 25, \"威海\", 25, \"承德\", 25, \"厦门\", 26, \"汕尾\", 26, \"潮州\", 26, \"丹东\", 27, \"太仓\", 27, \"曲靖\", 27, \"烟台\", 28, \"福州\", 29, \"瓦房店\", 30, \"即墨\", 30, \"抚顺\", 31, \"玉溪\", 31, \"张家口\", 31, \"阳泉\", 31, \"莱州\", 32, \"湖州\", 32, \"汕头\", 32, \"昆山\", 33, \"宁波\", 33, \"湛江\", 33, \"揭阳\", 34, \"荣成\", 34, \"连云港\", 35, \"葫芦岛\", 35, \"常熟\", 36, \"东莞\", 36, \"河源\", 36, \"淮安\", 36, \"泰州\", 36, \"南宁\", 37, \"营口\", 37, \"惠州\", 37, \"江阴\", 37, \"蓬莱\", 37, \"韶关\", 38, \"嘉峪关\", 38, \"广州\", 38, \"延安\", 38, \"太原\", 39, \"清远\", 39, \"中山\", 39, \"昆明\", 39, \"寿光\", 40, \"盘锦\", 40, \"长治\", 41, \"深圳\", 41, \"珠海\", 42, \"宿迁\", 43, \"咸阳\", 43, \"铜川\", 44, \"平度\", 44, \"佛山\", 44, \"海口\", 44, \"江门\", 45, \"章丘\", 45, \"肇庆\", 46, \"大连\", 47, \"临汾\", 47, \"吴江\", 47, \"石嘴山\", 49, \"沈阳\", 50, \"苏州\", 50, \"茂名\", 50, \"嘉兴\", 51, \"长春\", 51, \"胶州\", 52, \"银川\", 52, \"张家港\", 52, \"三门峡\", 53, \"锦州\", 54, \"南昌\", 54, \"柳州\", 54, \"三亚\", 54, \"自贡\", 56, \"吉林\", 56, \"阳江\", 57, \"泸州\", 57, \"西宁\", 57, \"宜宾\", 58, \"呼和浩特\", 58, \"成都\", 58, \"大同\", 58, \"镇江\", 59, \"桂林\", 59, \"张家界\", 59, \"宜兴\", 59, \"北海\", 60, \"西安\", 61, \"金坛\", 62, \"东营\", 62, \"牡丹江\", 63, \"遵义\", 63, \"绍兴\", 63, \"扬州\", 64, \"常州\", 64, \"潍坊\", 65, \"重庆\", 66, \"台州\", 67, \"南京\", 67, \"滨州\", 70, \"贵阳\", 71, \"无锡\", 71, \"本溪\", 71, \"克拉玛依\", 72, \"渭南\", 72, \"马鞍山\", 72, \"宝鸡\", 72, \"焦作\", 75, \"句容\", 75, \"北京\", 79, \"徐州\", 79, \"衡水\", 80, \"包头\", 80, \"绵阳\", 80, \"乌鲁木齐\", 84, \"枣庄\", 84, \"杭州\", 84, \"淄博\", 85, \"鞍山\", 86, \"溧阳\", 86, \"库尔勒\", 86, \"安阳\", 90, \"开封\", 90, \"济南\", 92, \"德阳\", 93, \"温州\", 95, \"九江\", 96, \"邯郸\", 98, \"临安\", 99, \"兰州\", 99, \"沧州\", 100, \"临沂\", 103, \"南充\", 104, \"天津\", 105, \"富阳\", 106, \"泰安\", 112, \"诸暨\", 112, \"郑州\", 113, \"哈尔滨\", 114, \"聊城\", 116, \"芜湖\", 117, \"唐山\", 119, \"平顶山\", 119, \"邢台\", 119, \"德州\", 120, \"济宁\", 120, \"荆州\", 127, \"宜昌\", 130, \"义乌\", 132, \"丽水\", 133, \"洛阳\", 134, \"秦皇岛\", 136, \"株洲\", 143, \"石家庄\", 147, \"莱芜\", 148, \"常德\", 152, \"保定\", 153, \"湘潭\", 154, \"金华\", 157, \"岳阳\", 169, \"长沙\", 175, \"衢州\", 177, \"廊坊\", 193, \"菏泽\", 194, \"合肥\", 229, \"武汉\", 273, \"大庆\", 279]# 将一维列表转换为(城市, AQI值)的元组列表data_pairs = [(data[i], data[i+1]) for i in range(0, len(data), 2)]# 创建Geo图表geo = Geo(init_opts=opts.InitOpts(width=\"1200px\", height=\"600px\"))geo.add_schema(maptype=\"china\")# 添加数据点和视觉映射(修改data_pair参数)geo.add( \"AQI\", data_pair=data_pairs, # 使用转换后的格式 type_=ChartType.SCATTER, symbol_size=8, label_opts=opts.LabelOpts(is_show=False),)# 设置视觉映射(保持不变)geo.set_global_opts( visualmap_opts=opts.VisualMapOpts( is_piecewise=True, pieces=[ {\"min\": 0, \"max\": 50, \"label\": \"0-50: 优\", \"color\": \"#00E400\"}, {\"min\": 51, \"max\": 100, \"label\": \"51-100: 良\", \"color\": \"#FFFF00\"}, {\"min\": 101, \"max\": 150, \"label\": \"101-150: 轻度污染\", \"color\": \"#FF7E00\"}, {\"min\": 151, \"max\": 200, \"label\": \"151-200: 中度污染\", \"color\": \"#FF0000\"}, {\"min\": 201, \"max\": 300, \"label\": \"201-300: 重度污染\", \"color\": \"#99004C\"}, {\"min\": 301, \"label\": \">300: 严重污染\", \"color\": \"#7E0023\"}, ], pos_left=\"right\", pos_top=\"middle\", ), title_opts=opts.TitleOpts(title=\"中国城市AQI分布图\"),)# 渲染图表geo.render(\"china_aqi_geo.html\")

实验七:数据可视化交互

实验 5:3D 地理 AQI 可视化
任务:结合 Geo3D 和 Bar3D 实现三维地理可视化:
1. 在地球模型上标记城市位置,高度表示 AQI 值
2. 使用 Map3D 配置光照效果和区域颜色(如中国区域高亮)
3. 展示不同地区 AQI 数值

import plotly.graph_objects as goimport pandas as pd# 城市 AQI 数据(与原代码一致)data = [ {\"城市\": \"北京\", \"AQI\": 90, \"经度\": 116.4074, \"纬度\": 39.9042}, {\"城市\": \"上海\", \"AQI\": 60, \"经度\": 121.4737, \"纬度\": 31.2304}, {\"城市\": \"广州\", \"AQI\": 75, \"经度\": 113.2644, \"纬度\": 23.1291}, {\"城市\": \"深圳\", \"AQI\": 65, \"经度\": 114.0579, \"纬度\": 22.5431}, {\"城市\": \"成都\", \"AQI\": 85, \"经度\": 104.0658, \"纬度\": 30.5728}, {\"城市\": \"武汉\", \"AQI\": 95, \"经度\": 114.3055, \"纬度\": 30.5928}, {\"城市\": \"西安\", \"AQI\": 110, \"经度\": 108.9480, \"纬度\": 34.2631}, {\"城市\": \"南京\", \"AQI\": 70, \"经度\": 118.7674, \"纬度\": 32.0415}, {\"城市\": \"杭州\", \"AQI\": 75, \"经度\": 120.1536, \"纬度\": 30.2874}, {\"城市\": \"重庆\", \"AQI\": 80, \"经度\": 106.5049, \"纬度\": 29.5331}, {\"城市\": \"天津\", \"AQI\": 85, \"经度\": 117.1901, \"纬度\": 39.1255}, {\"城市\": \"沈阳\", \"AQI\": 95, \"经度\": 123.4290, \"纬度\": 41.7968}, {\"城市\": \"哈尔滨\", \"AQI\": 100, \"经度\": 126.6424, \"纬度\": 45.7569}, {\"城市\": \"郑州\", \"AQI\": 105, \"经度\": 113.6524, \"纬度\": 34.7569}, {\"城市\": \"长沙\", \"AQI\": 85, \"经度\": 112.9822, \"纬度\": 28.1127}, {\"城市\": \"福州\", \"AQI\": 60, \"经度\": 119.2959, \"纬度\": 26.0819}, {\"城市\": \"济南\", \"AQI\": 90, \"经度\": 117.1200, \"纬度\": 36.6512}, {\"城市\": \"合肥\", \"AQI\": 75, \"经度\": 117.2856, \"纬度\": 31.8615}, {\"城市\": \"南昌\", \"AQI\": 70, \"经度\": 115.8921, \"纬度\": 28.6764}, {\"城市\": \"南宁\", \"AQI\": 65, \"经度\": 108.2901, \"纬度\": 22.8402}, {\"城市\": \"贵阳\", \"AQI\": 70, \"经度\": 106.7134, \"纬度\": 26.5784}, {\"城市\": \"昆明\", \"AQI\": 55, \"经度\": 102.7123, \"纬度\": 25.0406}, {\"城市\": \"拉萨\", \"AQI\": 40, \"经度\": 91.1106, \"纬度\": 29.6441}, {\"城市\": \"兰州\", \"AQI\": 100, \"经度\": 103.8343, \"纬度\": 36.0611}, {\"城市\": \"西宁\", \"AQI\": 95, \"经度\": 101.7793, \"纬度\": 36.6232}, {\"城市\": \"银川\", \"AQI\": 90, \"经度\": 106.2324, \"纬度\": 38.4867}, {\"城市\": \"乌鲁木齐\", \"AQI\": 115, \"经度\": 87.6177, \"纬度\": 43.8267}, {\"城市\": \"海口\", \"AQI\": 50, \"经度\": 110.3311, \"纬度\": 20.0319}, {\"城市\": \"石家庄\", \"AQI\": 105, \"经度\": 114.4891, \"纬度\": 38.0455}, {\"城市\": \"长春\", \"AQI\": 98, \"经度\": 125.3245, \"纬度\": 43.8375}, {\"城市\": \"呼和浩特\", \"AQI\": 88, \"经度\": 111.6409, \"纬度\": 40.8171}, {\"城市\": \"太原\", \"AQI\": 92, \"经度\": 112.5383, \"纬度\": 37.8737}, {\"城市\": \"大连\", \"AQI\": 78, \"经度\": 121.6126, \"纬度\": 38.9121}, {\"城市\": \"青岛\", \"AQI\": 82, \"经度\": 120.3350, \"纬度\": 36.0624}, {\"城市\": \"苏州\", \"AQI\": 73, \"经度\": 120.6055, \"纬度\": 31.3189}, {\"城市\": \"宁波\", \"AQI\": 68, \"经度\": 121.5405, \"纬度\": 29.8626}, {\"城市\": \"厦门\", \"AQI\": 62, \"经度\": 118.1029, \"纬度\": 24.4646}, {\"城市\": \"武汉\", \"AQI\": 95, \"经度\": 114.3055, \"纬度\": 30.5928}, {\"城市\": \"长沙\", \"AQI\": 85, \"经度\": 112.9822, \"纬度\": 28.1127}, {\"城市\": \"珠海\", \"AQI\": 60, \"经度\": 113.5269, \"纬度\": 22.2642}, {\"城市\": \"三亚\", \"AQI\": 55, \"经度\": 109.5135, \"纬度\": 18.2525}, {\"城市\": \"成都\", \"AQI\": 85, \"经度\": 104.0658, \"纬度\": 30.5728}, {\"城市\": \"西安\", \"AQI\": 110, \"经度\": 108.9480, \"纬度\": 34.2631}, {\"城市\": \"杭州\", \"AQI\": 75, \"经度\": 120.1536, \"纬度\": 30.2874}, {\"城市\": \"南京\", \"AQI\": 70, \"经度\": 118.7674, \"纬度\": 32.0415}, {\"城市\": \"重庆\", \"AQI\": 80, \"经度\": 106.5049, \"纬度\": 29.5331},]df = pd.DataFrame(data)# 创建 3D 散点图(与原代码一致)fig = go.Figure( data=go.Scatter3d( x=df[\"经度\"], y=df[\"纬度\"], z=df[\"AQI\"], text=df[\"城市\"] + \"
AQI: \"
+ df[\"AQI\"].astype(str), mode=\"markers\", marker=dict( size=df[\"AQI\"] / 10, color=df[\"AQI\"], colorscale=\"YlOrRd\", colorbar=dict(title=\"AQI 值\"), opacity=0.8, ), ))# 设置布局(优化相机视角和坐标轴)fig.update_layout( title=dict( text=\"中国城市AQI三维地理分布\", x=0.5, font=dict(size=24, color=\"white\") ), scene=dict( xaxis=dict(title=\"经度\", showgrid=False, titlefont=dict(color=\"white\")), yaxis=dict(title=\"纬度\", showgrid=False, titlefont=dict(color=\"white\")), zaxis=dict(title=\"AQI值\", showgrid=False, titlefont=dict(color=\"white\")), camera=dict(eye=dict(x=1.8, y=1.8, z=1.2)), aspectratio=dict(x=1, y=1, z=0.5) ), paper_bgcolor=\"rgba(0,0,0,0)\", plot_bgcolor=\"rgba(0,0,0,0)\", margin=dict(l=0, r=0, b=0, t=60),)# 添加中国地图背景(使用 add_layout_image 正确方法)fig.add_layout_image( dict( source=\"https://img-blog.csdnimg.cn/20230426153240606.png\", # 地图图片地址 xref=\"x\", yref=\"y\", x=df[\"经度\"].min(), y=df[\"纬度\"].min(), # 图片左下角坐标 sizex=df[\"经度\"].max() - df[\"经度\"].min(), # 图片宽度(经度范围) sizey=df[\"纬度\"].max() - df[\"纬度\"].min(), # 图片高度(纬度范围) opacity=0.15, layer=\"below\" # 图片层位于数据下方 ))# 保存为 HTMLfig.write_html(\"aqi_3d_geo.html\", auto_open=True)

实验七:数据可视化交互
本次数据可视化交互实验围绕全国空气质量展开。目的是了解原则、掌握分类与常见技术。实验中安装pyecharts,用其完成多项任务,如绘制 AQI 横向对比条形图、等级分布饼图、多城市对比仪表盘等。过程中遇到代码兼容等问题并解决。通过实验,提升了数据可视化编程与分析能力,也认识到其在决策支持中的重要性。