继Python生态绘图类库:Plotly、Altair、bqplot、plotlet之后,本文继续汇总Python生态下,特定领域下的绘图类库。
Folium
项目主页,地图画图工具开源(GitHub,7.4K Star,2.3K Fork)类库,基于Leaflet.js,可在Jupyter Notebook里画出可缩放、可拖拽、带标记点的交互式地图。
适用场景
| 场景 | 说明 |
|---|---|
| 数据可视化报告 | 在Jupyter里展示地理数据分布 |
| 门店/网点分布图 | 批量打点,直观看到覆盖范围 |
| 路线规划展示 | 把GPS轨迹画出来 |
| 热力图分析 | 如人口密度、事故高发区 |
实战
基于pip安装:pip install folium
示例:
importfolium# 创建地图,定位到北京m=folium.Map(location=[39.9042,116.4074],zoom_start=12)# 加标记点folium.Marker([39.9042,116.4074],popup="天安门",icon=folium.Icon(color="red",icon="info-sign")).add_to(m)# 保存HTML文件m.save("map.html")# 在Jupyter里直接显示m批量打点:
importfoliumfromfolium.pluginsimportHeatMapimportpandasaspd# 门店数据stores=pd.DataFrame({'name':['店A','店B','店C'],'lat':[39.90,39.92,39.88],'lng':[116.40,116.42,116.38]})m=folium.Map(location=[39.90,116.40],zoom_start=13)for_,rowinstores.iterrows():folium.Marker([row['lat'],row['lng']],popup=row['name']).add_to(m)# 用经纬度数据生成热力图heat_data=[[row['lat'],row['lng']]for_,rowinstores.iterrows()]HeatMap(heat_data).add_to(m)m效果图
画区域、画路径
# 画折线folium.PolyLine(locations=[(39.90,116.40),(39.92,116.42),(39.88,116.38)],color='blue',weight=5).add_to(m)# 画圆,如覆盖范围folium.Circle(location=[39.90,116.40],radius=1000,# 米color='red',fill=True).add_to(m)展示效果
PlotNine
官网,图形语法绘图开源(GitHub,4.8K Star,254 Fork)库,把ggplot2风格的Grammar of Graphics带到Python,强调数据、映射、几何对象、坐标和分面等概念,比先画线再调样式的过程更声明式,官方文档。
适合统计探索、分组对比、教学材料、希望用一致语法组织复杂统计图、从R或ggplot2迁移来的团队,以及需要统一图形语法的分析脚本。
不适合极复杂的交互式Web图表,或需要直接操控Matplotlib底层每个Artist的精细场景。
特点
- 语法清晰:用
aes、geom、facet、coord组合图表,表达意图很明确 - 适合统计图:分面、颜色映射、几何层叠很自然
- 承接Pandas:DataFrame字段直接进入映射,分析脚本里衔接顺。
实战
基于pip安装:pip install plotnine
示例:
importpandasaspdfromplotnineimportaes,coord_flip,facet_wrap,geom_point,geom_col,ggplot,stat_smooth,theme_xkcd,theme_tufte,theme_minimalfromplotnine.dataimportmtcars(ggplot(mtcars,aes("wt","mpg",color="factor(gear)"))# 调用mtcars数据集,以车重wt与每加仑行驶英里数mpg为坐标,颜色受gear影响+geom_point())绘制效果图
(ggplot(mtcars,aes("wt","mpg",color="factor(gear)"))+geom_point()+stat_smooth(method="lm")# 绘制线性拟合曲线)效果图(需要等十几秒钟):
(ggplot(mtcars,aes("wt","mpg",color="factor(gear)"))+geom_point()+stat_smooth(method="lm")+facet_wrap("gear")# 按gear进行分组,以多面展示数据)效果图
(ggplot(mtcars,aes("wt","mpg",color="factor(gear)"))+geom_point()+stat_smooth(method="lm")+facet_wrap("gear")+theme_xkcd()# 绘制手绘风格主题# + theme_tufte() # Tufte 风格主题# + theme_minimal() # 系统默认# + theme_bw() # 系统默认)可能会输出字体不存在,渲染没有什么较大影响
findfont: Font family 'xkcd' not found. findfont: Font family 'Humor Sans' not found.不想看到警告信息,添加两行代码:
importlogging logging.getLogger('matplotlib.font_manager').setLevel(logging.ERROR)渲染效果:
也可从xkcd-font官网下载xkcd.ttf字体文件。
更多示例:
df=pd.DataFrame({"x":[1,2,3],"y":[2,5,3]})p=ggplot(df,aes("x","y"))+geom_point()fig=p.draw(show=False)print("layers:",len(p.layers))print("axes:",len(fig.axes))df=pd.DataFrame({"team":["A","B","C"],"score":[7,4,9]})p=ggplot(df,aes("team","score"))+geom_col(fill="#4c78a8")+coord_flip()fig=p.draw(show=False)print("layers:",len(p.layers))print("coord:",type(p.coordinates).__name__)print("axes:",len(fig.axes))df=pd.DataFrame({"x":[1,2,1,2],"y":[3,5,2,7],"team":["A","A","B","B"]})p=ggplot(df,aes("x","y",color="team"))+geom_point(size=3)+facet_wrap("team")fig=p.draw(show=False)print("facets:",type(p.facet).__name__)print("panels:",len(fig.axes))解读:把不同统计视角拆成geom和facet,比在一段imperative代码里不断改axes更容易维护。
注意事项:
- 固定输入字段、数据量范围和缺失值策略
- 明确图表是静态导出、Notebook交互、桌面GUI还是Web嵌入
- 在目标运行环境里做一次渲染或导出验证
LeafMap
官网,基于folium,开源(GitHub,3.8K Star,469 Fork)零代码地理数据分析与交互式绘图包。
能力
- 超多后端随意切换:可切换到
folium、ipyleaflet、kepler.gl、pydeck、bokeh等不同后端,根据场景选最顺手的工具 - 交互式绘图工具:内置图形界面,很多操作(如加载数据、画图)不用写代码,在Jupyter里点点鼠标就能完成
- 分析能力强大:集成WhiteboxTools分析工具库,可直接在地图上进行水文分析、地形分析、LiDAR数据处理等
- 对新手和专家都友好:初学者能快速上手出图,专业用户也能用它处理复杂的空间数据和分析任务
实战
基于pip安装:pip install leafmap
示例:
PyGal
官网,SVG 图表生成开源(GitHub,2.8K Star,419 Fork)。创建图表对象、设置标签、添加series、渲染为SVG。
相比大型交互式可视化框架,更适合在文档、邮件图表、静态页面和报告里产出可缩放矢量图、需要SVG文件的自动化脚本,以及需要轻量、可嵌入、无需复杂前端依赖时。适合在构建流程里生成、缓存、嵌入,而不是依赖运行时再画。
不适合高度复杂的交互式分析平台,或需要海量数据点实时重绘的科学计算界面。
特点
- SVG输出:图表天然可缩放,适合文档和静态页面
- API简洁:Bar、Line、Radar等图表对象直接添加数据即可
- 依赖轻:不用完整前端框架,也能生成可用图表资产
实战
基于pip安装:pip install pygal
示例
importpygal chart=pygal.Bar()chart.title="sales"chart.x_labels=["Jan","Feb","Mar"]chart.add("sales",[120,160,90])svg=chart.render()print("series:",len(chart.raw_series))print("svg bytes:",len(svg))chart=pygal.Line(interpolate="cubic")chart.add("A",[1,3,2,5])chart.add("B",[2,2,4,3])names=[meta["title"]fordata,metainchart.raw_series]svg=chart.render()print("series names:",names)print("series count:",len(chart.raw_series))print("svg bytes:",len(svg))chart=pygal.Radar()chart.x_labels=["speed","quality","cost"]chart.add("plan A",[8,7,5])chart.add("plan B",[6,9,7])svg=chart.render(is_unicode=True)print("radar labels:",list(chart.x_labels))print("has svg:",svg.lstrip().startswith("<?xml"))CartoPy
面向地图绘制和地理投影的开源(GitHub,1.6K Star,396 Fork)库,常和Matplotlib、NumPy、GeoPandas一起使用。把经纬度坐标、投影坐标、地图要素和坐标轴变换放进同一套模型里管理。适合气象图、海洋航线、遥感辅助图、区域统计地图等场景下的可视化,官方文档。
特点
- 投影清楚:CRS对象负责坐标系统和变换,适合在图上混合经纬度、墨卡托等坐标
- 要素可控:Natural Earth要素可按类别和比例尺组织,便于控制海岸线、陆地等素材
- 生态兼容:和Matplotlib配合紧密,适合把科学计算结果落到地图视图里
不适合只想快速在网页里拖动地图的场景;这类需求通常Leaflet、Mapbox或Folium更合适。
实战
基于pip安装:pip install cartopy
示例:
importcartopy.crsasccrsimportcartopy.featureascfeatureimportnumpyasnp src=ccrs.PlateCarree()dst=ccrs.Mercator()pts=dst.transform_points(src,np.array([0,120]),np.array([0,30]))fmt=lambdarow:[float(round(v,2))forvinrow[:2]]print("threshold:",round(src.threshold,3))print("points:",pts.shape)print("x0/y0:",fmt(pts[0]))print("x1/y1:",fmt(pts[1]))land=cfeature.NaturalEarthFeature("physical","land","110m")print("feature:",land.name)print("category:",land.category)print("scale:",land.scale)解读:
- 把经纬度点转换到Web/墨卡托类坐标,验证数据坐标能进入目标投影
- 定义Natural Earth地图要素,后续可交给Matplotlib轴对象渲染
注意事项:
- 固定Python、核心库和系统依赖版本,避免环境漂移
- 用小样本覆盖输入边界、空值、异常值和坐标/数组维度
- 把外部服务、投影数据或编译依赖写进部署文档
floWeaver
开源(GitHub,464 Star,89 Fork)流数据可视化,可将类似于“源-目标-数值”这种表单数据,变成比例精准、配色高级的桑基图,官方文档。
组件:
- floWeaver:负责逻辑层
- ipysankeywidget:负责在Jupyter里渲染图表
用ProcessGroup定义聚合类别,用Waypoint标记节点,SankeyDefinition负责布局,Weave负责数据映射。
实战
基于pip安装:pip install floweaver
示例:
fromfloweaverimportSankeyDefinition,WeavefromfloweaverimportProcessGroup,Waypointimportpandasaspd group_elect=ProcessGroup('电子产品')group_home=ProcessGroup('家居生活')group_cloth=ProcessGroup('服饰美妆')w_elect=Waypoint(group_elect,title='电子')w_home=Waypoint(group_home,title='家居')w_cloth=Waypoint(group_cloth,title='服装')sankey_def=SankeyDefinition(flows=[(w_elect,w_home),(w_elect,w_cloth),(w_home,w_cloth)],waypoints=[w_elect,w_home,w_cloth])data=pd.DataFrame({'source':['电子','电子','家居'],'target':['家居','服装','服装'],'value':[100,50,30]})weave=Weave(sankey_def,data,link_columns=['source','target','value'])weave.to_widget()sankey_def.flows=[(w_elect,w_home),(w_home,w_cloth)]weave_new=Weave(sankey_def,data,link_columns=['source','target','value'])weave_new.to_widget()TODO:上述代码在2.0.1版本,跑不通。
优势在于它把“流”的语法抽象得非常干净,几行代码就能出专业级桑基图,且配色省心。
不足,高度绑定ipysankeywidget,只能用于Jupyter Notebook或Lab,没法直接导出PNG或用在Django网站上。