数据可视化实验:数据可视化交互
一、引言与实验原理
设计可视化系统或选择交互方式的时候,除了能够完成任务本身之外,还要遵循一些基本的原则。例如,交互的延时性需要在用户可以接受的范围之内,并有效控制用户交互的成本。这些基本原则对交互的效果起着至关重要的作用富。
另外,交互的技术有很多种,本次实验是对文本进行可视化生成词云图片与传统的统计技术对比。
交互的原则、交互的分类以及常见的交互技术,尤其是几种常见的交互技术,只有熟练掌握并使用恰当,才可能设计出用户体验良好的可视化应用。尽管交互的技术有很多种,但交互技术本身并无优劣之分,选择哪种交互技术的依据是具体的场景和应用需求。
二、实验目的与实验环境
本次实验学习的是比例数据可视化技术的操作方法。使用Python完成。主要包括:
- 了解数据可视化的一般原则
- 掌握数据可视化的分类
- 掌握数据可视化的常见技术
- 对全国的空气质量进行可视化分析并进行数据统计技术对比
实验环境:
- OS:win11
- python:v3.11.5
三、实验步骤
0、数据可视化的一般原则
数据可视化是将复杂数据转化为直观视觉形式的过程,其核心原则旨在通过科学的设计平衡信息传达效率与用户体验。首先,准确性是基础,要求数据呈现必须真实反映原始信息,避免比例误导或冗余干扰。例如,选择合理的图表比例和刻度,确保视觉元素与数据本质一致。其次,简洁性强调去除冗余装饰,聚焦核心信息,通过有限的颜色、清晰的标签和精简的布局降低认知负担,例如使用单色系柱状图替代复杂3D图形。
在视觉设计层面,一致性原则要求保持色彩、字体、符号等元素的统一,这不仅能增强专业度,还能帮助用户快速建立跨图表的认知关联。同时,美学与功能平衡尤为重要,需通过自然配色、合理对比提升视觉吸引力,但避免过度设计导致信息失真。例如,采用色盲友好配色并辅以纹理标记,既能满足美学需求又兼顾可访问性。
交互性与故事性则是现代数据可视化的重要延伸。交互设计通过悬停提示、动态筛选等功能支持用户自主探索数据,例如在销售仪表盘中联动地图与趋势图实现多维度分析。而故事性则通过逻辑连贯的叙事结构引导用户理解数据内涵,如结合时间轴动画展示气候变化过程,使抽象数据转化为具象认知。这些原则共同构成数据可视化的方法论框架,推动从数据展示到决策支持的跨越。
1、安装 Pyecharts
在终端输入pip show pyecharts查看是否安装依赖库

如未安装,请在终端输入pip install pyecharts安装这个库
2、下载数据
数据文件(data.txt)表示了一些城市某天的空气质量指数(AQI)

3、实验任务
实验1:AQI 横向对比条形图
任务:使用Pyecharts 绘制各城市AQI 值的横向条形图,要求:
- 按AQI 从高到低排序
- 添加全局配置项:标题为“城市AQI 对比”,坐标轴名称分别为“AQI 指数”和“城市”
- 使MarkLine 标记AQI 均值线(参考值:80),并设置不同颜色区分高于/低于均值的城市
from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import JsCode
import ast
with open(r'e:\Microsoft VS Code\BDV\BDV Exam\Chapter 8\data.txt', 'r', encoding='utf-8') as f:
data = f.read()
data_list = ast.literal_eval('[' + data + ']')
cities = data_list[::2]
aqi_values = [float(x) for x in data_list[1::2]]
city_aqi = list(zip(cities, aqi_values))
city_aqi.sort(key=lambda x: float(x[1]))
cities = [item[0] for item in city_aqi]
aqi_values = [item[1] for item in city_aqi]
aqi_reference = 80
bar = (
Bar()
.add_xaxis(cities)
.add_yaxis(
"AQI值",
aqi_values,
label_opts=opts.LabelOpts(position="right"),
itemstyle_opts=opts.ItemStyleOpts(
color=JsCode(
"""
function(params) {
return params.value >= 80 ? '#FF0000' : '#00FF00';
}
"""
)
)
)
.set_global_opts(
title_opts=opts.TitleOpts(title="城市AQI对比"),
xaxis_opts=opts.AxisOpts(name="城市"),
yaxis_opts=opts.AxisOpts(name="AQI指数"),
datazoom_opts=[opts.DataZoomOpts(type_="slider")],
)
.set_series_opts(
markline_opts=opts.MarkLineOpts(
data=[{"xAxis": aqi_reference, "name": "参考值"}]
)
)
.reversal_axis()
)
bar.render("1.html")
实现结果:

实验2:AQI 等级分布饼图
任务:基于AQI 等级划分(优/良/轻度污染/中度污染/重度污染),绘制饼图并添加交互功能:
- 使用Pie 图表展示各等级下城市数量占比
- 标签显示百分比和等级名称,突出显示占比最大的扇区
- 添加点击事件:单击扇区时弹出该等级详细城市数量及城市名称列表
from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.commons.utils import JsCode
def read_data():
cities = {}
data_path = r'e:\Microsoft VS Code\BDV\BDV Exam\Chapter 8\data.txt'
with open(data_path, 'r', encoding='utf-8') as f:
content = f.read().strip()
items = content.replace('"', '').split(',')
for i in range(0, len(items), 2):
if i + 1 < len(items):
city = items[i].strip()
aqi = int(items[i + 1].strip())
cities[city] = aqi
return cities
def get_aqi_level(aqi):
if aqi <= 50:
return '优'
elif aqi <= 100:
return '良'
elif aqi <= 150:
return '轻度污染'
elif aqi <= 200:
return '中度污染'
else:
return '重度污染'
cities_data = read_data()
level_data = {}
level_cities = {}
for city, aqi in cities_data.items():
level = get_aqi_level(aqi)
level_data[level] = level_data.get(level, 0) + 1
if level not in level_cities:
level_cities[level] = []
level_cities[level].append(city)
pie = Pie()
data_pairs = [(k, v) for k, v in level_data.items()]
max_value = max(level_data.values())
pie.add(
series_name="AQI等级分布",
data_pair=data_pairs,
radius=["40%", "75%"],
label_opts=opts.LabelOpts(
formatter="{b}: {d}%",
font_size=12,
position="outside"
)
)
pie.set_global_opts(
title_opts=opts.TitleOpts(title="城市空气质量指数(AQI)等级分布"),
legend_opts=opts.LegendOpts(orient="vertical", pos_left="left"),
)
pie.set_series_opts(
label_opts=opts.LabelOpts(formatter="{b}: {d}%"),
tooltip_opts=opts.TooltipOpts(
trigger="item",
formatter=JsCode(
"function(params){"
" return params.name + '<br/>数量: ' + params.value +"
" '<br/>城市: ' + " + str({k: ','.join(v) for k, v in level_cities.items()}) +
"[params.name];"
"}"
)
)
)
output_path = r'e:\Microsoft VS Code\BDV\BDV Exam\Chapter 8\2.html'
pie.render(output_path)
实现结果:

实验3:多城市AQI 对比仪表盘
任务:使用Tab 或Page 组件构建多图表仪表盘:
- 第一选项卡:显示AQI 前10 城市的横向条形图
- 第二选项卡:展示西北地区城市AQI 散点数据(添加回归线)与东部城市AQI 散点数据(添加回归线)的对比
- 第三选项卡:组合折线图(各地区AQI 指数的变化)
- 要求所有图表共享主题风格(如ThemeType.DARK)
import pandas as pd
import numpy as np
from pyecharts import options as opts
from pyecharts.charts import Bar, Tab, Scatter, Line
from pyecharts.commons.utils import JsCode
from scipy import stats
with open(r'e:\Microsoft VS Code\BDV\BDV Exam\Chapter 8\data.txt', 'r', encoding='utf-8') as f:
data = [x.strip() for x in f.read().strip().split(',')]
data = [x for x in data if x]
cities = [city.strip('"') for city in data[::2] if city.strip('"')]
aqi_values = [int(x) for x in data[1::2] if x.strip()]
if len(cities) != len(aqi_values):
print(f"警告:城市数量({len(cities)})和AQI值数量({len(aqi_values)})不匹配")
else:
print(f"数据读取成功:共{len(cities)}个城市")
df = pd.DataFrame({'City': cities, 'AQI': aqi_values})
def assign_region(city):
northwest_provinces = ['西安', '延安', '咸阳', '铜川', '渭南', '宝鸡', # 陕西
'兰州', '嘉峪关', '金昌', # 甘肃
'西宁', # 青海
'银川', '石嘴山', # 宁夏
'乌鲁木齐', '克拉玛依', '库尔勒'] # 新疆
east_provinces = ['北京', '天津', # 直辖市
'石家庄', '唐山', '秦皇岛', '邯郸', '邢台', '保定', '张家口', '承德', '沧州', '廊坊', '衡水', # 河北
'上海', # 上海
'南京', '无锡', '徐州', '常州', '苏州', '南通', '连云港', '淮安', '盐城', '扬州', '镇江', '泰州', '宿迁', # 江苏
'杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水', # 浙江
'福州', '厦门', '泉州', # 福建
'济南', '青岛', '淄博', '枣庄', '东营', '烟台', '潍坊', '济宁', '泰安', '威海', '日照', # 山东
'广州', '深圳', '珠海', '汕头', '韶关', '惠州', '东莞', '中山', '江门', # 广东
'海口', '三亚'] # 海南
if city in northwest_provinces:
return '西北'
elif city in east_provinces:
return '东部'
else:
return '其他'
df['Region'] = df['City'].apply(assign_region)
theme_style = {
"backgroundColor": "#ffffff",
"textStyle": {"color": "#333"},
"title": {"textStyle": {"color": "#333"}},
}
def create_bar_chart():
top_10 = df.nlargest(10, 'AQI')
bar = (
Bar()
.add_xaxis(top_10['City'].tolist())
.add_yaxis("AQI指数", top_10['AQI'].tolist())
.reversal_axis()
.set_global_opts(
title_opts=opts.TitleOpts(title="AQI前10城市排名"),
xaxis_opts=opts.AxisOpts(name="城市"),
yaxis_opts=opts.AxisOpts(name="AQI指数")
)
)
return bar
def create_scatter_chart():
northwest = df[df['Region'] == '西北']
east = df[df['Region'] == '东部']
scatter = (
Scatter()
.add_xaxis(list(range(len(northwest))))
.add_yaxis("西北城市", northwest['AQI'].tolist(),
markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")]))
.add_yaxis("东部城市", east['AQI'].tolist(),
markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")]))
.set_global_opts(
title_opts=opts.TitleOpts(title="西北与东部城市AQI对比"),
xaxis_opts=opts.AxisOpts(name="城市序号"),
yaxis_opts=opts.AxisOpts(name="AQI指数")
)
)
return scatter
def create_line_chart():
region_aqi = df.groupby('Region')['AQI'].mean()
line = (
Line()
.add_xaxis(region_aqi.index.tolist())
.add_yaxis("地区平均AQI", region_aqi.values.tolist(),
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")]))
.set_global_opts(
title_opts=opts.TitleOpts(title="各地区AQI指数对比"),
xaxis_opts=opts.AxisOpts(name="地区"),
yaxis_opts=opts.AxisOpts(name="平均AQI指数")
)
)
return line
tab = Tab()
tab.add(create_bar_chart(), "AQI前10城市")
tab.add(create_scatter_chart(), "西北vs东部城市对比")
tab.add(create_line_chart(), "地区AQI趋势")
tab.render('3.html')
实现结果:
AQI前十城市排名:

西北VS东部城市对比:

地区AQI趋势:

实验4:2D 地理AQI 可视化
任务:结合Geo 实现二维地理可视化:
- 在中国地图上标记城市位置,使用不同颜色表示AQI 值
- 展示不同地区AQI 数值
from pyecharts import options as opts
from pyecharts.charts import Geo
import re
with open('data.txt', 'r', encoding='utf-8') as f:
content = f.read()
pattern = r'"([^"]+)", (\d+)'
matches = re.findall(pattern, content)
data_pairs = [(city, int(value)) for city, value in matches]
cities = [pair[0] for pair in data_pairs]
values = [pair[1] for pair in data_pairs]
geo = (
Geo()
.add_schema(maptype="china")
.add(
"AQI指数",
data_pairs,
type_="scatter",
symbol_size=8,
label_opts=opts.LabelOpts(is_show=True, formatter="{b}: {c}"),
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=True))
.set_global_opts(
title_opts=opts.TitleOpts(title="中国城市AQI分布图"),
visualmap_opts=opts.VisualMapOpts(
min_=min(values),
max_=max(values),
range_text=["高", "低"],
is_piecewise=False,
is_calculable=True,
pos_right="10%",
item_width=30,
item_height=140,
border_width=0,
range_color=["#00FF00", "#FFFF00", "#FF0000"] # 绿-黄-红
),
tooltip_opts=opts.TooltipOpts(
trigger="item",
formatter="{b}: {c}"
)
)
)
geo.render("4.html")
实现结果:

实验5:3D 地理AQI 可视化
任务:结合Geo3D 和Bar3D 实现三维地理可视化:
- 在地球模型上标记城市位置,高度表示AQI 值
- 使用Map3D 配置光照效果和区域颜色(如中国区域高亮)
- 展示不同地区AQI 数值
import pandas as pd
import pydeck as pdk
import numpy as np
import os
file_path = 'E:\Microsoft VS Code\BDV\BDV Exam\Chapter 8\data.txt'
try:
data = pd.read_csv(file_path, sep=',', names=['城市名', 'AQI值', '东部/西部', '纬度', '经度'])
except Exception as e:
print(f"读取数据失败:{e}")
exit(1)
data['latitude'] = pd.to_numeric(data['纬度'], errors='coerce')
data['longitude'] = pd.to_numeric(data['经度'], errors='coerce')
data['aqi'] = pd.to_numeric(data['AQI值'], errors='coerce')
data = data.dropna(subset=['latitude', 'longitude', 'aqi'])
print("数据中经度范围:", data['longitude'].min(), data['longitude'].max())
print("数据中纬度范围:", data['latitude'].min(), data['latitude'].max())
china_bounds = [
(73.66, 18.14), (134.77, 18.14), (134.77, 53.56), (73.66, 53.56)
]
earth_surface = pdk.Layer(
'RasterLayer',
data='https://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer/tile/0/0/0',
bounds=china_bounds,
opacity=0.8,
texture_gain=[1.0, 1.0]
)
aqi_layer = pdk.Layer(
'ColumnLayer',
data=data,
get_position='[longitude, latitude]',
get_elevation='aqi * 200',
get_radius=40000,
get_fill_color='''[
Math.max(255 - aqi * 1.5, 10), # R
Math.max(255 - aqi * 1.5, 10), # G
Math.max(255 - aqi * 1.5, 10), # B
200 # 透明度
]''',
elevation_scale=1,
pickable=True,
auto_highlight=True
)
border_layer = pdk.Layer(
'PolygonLayer',
data=[{'coordinates': [china_bounds], 'fill_color': [0, 0, 0, 100]}],
get_polygon='coordinates',
opacity=0.5,
stroked=True,
line_width_min_pixels=3,
line_color=[255, 255, 255]
)
view_state = pdk.ViewState(
latitude=35.8,
longitude=104.1,
zoom=2.5,
pitch=60,
bearing=0
)
styler = pdk.Deck(
layers=[earth_surface, border_layer, aqi_layer],
initial_view_state=view_state,
tooltip={"text": "城市:{城市名}\nAQI值:{aqi}\n区域:{东部/西部}"},
map_style='light' # 使用浅色地图样式(黑白基调)
)
output_dir = os.path.expanduser("~/Desktop")
os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, "5.html")
try:
styler.to_html(output_path)
print(f"\n✅ 黑白配色地图已保存到:{output_path}")
print("请使用Chrome或Firefox浏览器打开查看效果")
print("操作提示:")
print(" - 鼠标拖动:旋转地图")
print(" - 滚轮:缩放地图")
print(" - 右键拖动:倾斜视角")
print(" - 点击柱状体:查看城市详情")
except Exception as e:
print(f"\n出错:{e}")
实现结果:

四、总结与心得
本次实验围绕数据可视化交互展开,基于Python的Pyecharts库对全国城市空气质量数据进行多维度可视化分析。通过完成横向条形图对比AQI值、饼图展示等级分布、多选项卡仪表盘综合分析、2D及3D地理可视化等任务,实践了数据可视化的准确性、简洁性等核心原则,实现了从数据清洗、图表绘制到交互功能设计的完整流程,直观呈现了不同城市及区域的空气质量特征。
实验过程中,既掌握了Pyecharts库的各类图表使用技巧(如通过颜色区分数据状态、添加标记线和点击事件),也体会到数据处理的严谨性对可视化效果的关键作用。尽管3D地理可视化部分代码尚未完善,但通过多类型图表的对比与联动,已充分展现数据可视化在辅助分析决策中的价值,为后续深入学习复杂交互技术和多源数据整合奠定了基础。

被折叠的 条评论
为什么被折叠?



