Python旅游景点数据分析实战:从数据清洗到可视化洞察 简介数据分析项目中原始数据往往包含缺失值、重复记录和异常文本直接分析容易得出错误结论。如何借助pandas等工具完成高效的数据清洗与特征构建并将结果通过可视化清晰呈现是数据挖掘流程中的核心环节。掌握这一套方法论可以灵活应用于景区热度评估、门票定价分析、游客口碑洞察等真实业务场景帮助产品、运营和决策者从海量数据中提取有价值的信息。本文以四川省旅游景点数据集为例完整演示了从数据探查、缺失值处理、重复值去重、派生特征构建到地理分布、等级价格、热度评分等维度的分析过程并给出可复现的Python代码与可视化方案。无论你是刚入门的数据分析师还是希望提升数据处理效率的从业者这套分析框架都能直接迁移到其他地域或行业的数据项目中。 做旅游景点数据分析这个方向最容易踩的坑就是“拿到的数据根本没法直接用”。这份四川省旅游景点数据集代码案例正好把从原始数据到可视化洞察的完整链路跑通了。我拿到这份材料之后完整过了一遍今天这篇就把整个分析思路、数据预处理、实操代码和踩过的坑一次性说清楚想拿省份级景区数据练手的朋友可以直接参考复现。先交代一下这套内容适合谁刚学完Python基础和pandas、正愁没有实战数据的新手或者想了解省级旅游数据从清洗到可视化全流程的产品、运营同学都可以拿它当一份标准的分析范式。它最大的价值不是“四川”这两个字而是整个分析框架——换任何省份、任何行业的地域型数据这套思路都能平移过去。1. 项目整体设计思路为什么选四川旅游数据做分析1.1 四川旅游数据背后的分析价值四川省的旅游资源在全国范围内都非常有代表性既有九寨沟、峨眉山这类世界级自然景观又有都江堰、三星堆这类人文遗址还有川西高原上大量的小众目的地。这种“多层次、多类型、分布广”的特点让四川景区的数据非常适合做地域维度的分析——你能在一份数据里同时看到自然景观和人文景区的差异也能对比成熟景区和新兴景区的热度差距分析结论的丰富度比其他单一类型景区数据高很多。我当时拿到这套数据的第一反应是先别急着跑代码而是想清楚“我要从这份数据里回答什么问题”。这套案例的设计逻辑也是围绕几个核心问题展开的四川的A级景区在省域内是怎样分布的哪些市州是旅游资源的富集区景区等级和门票价格之间有没有明显关系5A景区是不是一定比4A贵游客的热度、评分和景区类型有没有相关趋势从数据和业务角度看哪些景区是被低估的哪些已经过热了带着这些问题去做分析整个过程就不会变成“对着数据机械地画图”而是一路有假设、有验证最后能落到业务建议上。1.2 数据集的字段设计逻辑这份数据集的核心字段我觉得设计得比较合理不是简单的“景点名称位置”两列而是考虑了后续分析的可扩展性。主要字段包括字段名字段含义分析用途name景区名称基础标识city所在市州地域分布分析levelA级等级5A/4A/3A等等级与价格、热度交叉分析type景区类型自然/人文/综合等类型差异对比score游客评分质量维度分析heat热度指数受欢迎程度分析ticket_price门票价格价格敏感度分析lat / lng纬度/经度地理可视化description景区简介文本挖掘扩展分析这个字段组合的思路很清晰常见的景区数据其实只有名称和介绍但一旦补上“等级、价格、坐标、评分”这些维度它就可以支持从“地图分布”到“价格策略”再到“口碑评价”的全套分析。如果你以后自己采集数据建议也尽量按这个字段结构去设计宁可前期多花点时间补全信息也不要拿到手再返工。1.3 项目文件结构与技术选型解压这个rar之后里面的文件组织方式也值得参考基本是一套标准的“数据集代码”项目结构四川省旅游景点数据分析/ ├── data/ │ ├── raw/ # 原始数据 │ │ └── sichuan_attractions.csv │ ├── processed/ # 清洗后的数据 │ │ └── attractions_clean.csv │ └── output/ # 分析结果 │ ├── figures/ # 图表输出 │ └── summary_tables/ # 汇总统计表 ├── notebooks/ │ └── analysis.ipynb # 主分析代码 ├── src/ │ ├── data_clean.py # 数据清洗模块 │ ├── visualization.py # 可视化模块 │ └── utils.py # 通用工具函数 └── README.md # 项目说明文档技术选型方面用的是Python的数据分析三件套pandas做数据清洗和聚合matplotlib和plotly做静态图和交互图部分地图可视化用了pyecharts。这套组合是目前做数据分析项目最主流的搭配不会太复杂也足够支撑省级数据量的分析场景。如果数据量再大一个量级比如到了千万行级别那才会考虑Spark当前阶段用pandas处理几千条景区数据已经是杀鸡用牛刀了。2. 数据预处理与清洗实操拿到原始数据后先做这三件事2.1 数据读取与初步探查刚开始我习惯先跑一个info()和head()快速判断数据质量而不是着急做清洗。这份数据的原始CSV大概有1000多条记录覆盖了四川大部分A级景区但问题也不少。import pandas as pd df pd.read_csv(data/raw/sichuan_attractions.csv, encodingutf-8) print(df.info()) print(df.head(10))跑完之后会发现几个典型问题score列存在缺失值ticket_price列有部分“免费”的非数值文本还有少数景区的坐标信息是空的。这些都是真实数据的常态也是这个案例最值得学习的地方——真实的景区数据永远不会像教科书样例一样整齐。2.2 缺失值、重复值和异常值的处理策略数据清洗这一部分我总结了一个三层的处理顺序基本能覆盖大多数情况第一层处理缺失值。对于score这种评分类字段如果缺失比例不超过5%我一般直接用同等级景区的平均值填充对于坐标字段如果缺失我用该城市其他景区的平均经纬度去近似同时打一个“近似坐标”的标记对于简介文本的缺失直接保留空值后面分析时再处理。第二层处理重复值。景区数据里比较坑的是同一条记录因为来源不同会出现“名字略微不同”的重复比如“九寨沟”和“九寨沟风景名胜区”其实是一个地方。这种情况单纯用drop_duplicates()是去不掉的我处理的方法是先对名称做标准化去掉“风景名胜区”这类后缀再基于标准化后的名称去重这样可以避免大量误删。第三层处理异常值。门票价格的明显异常比较好发现比如一个3A景区标了500块门票基本就是录入错误。我的处理方式是先画出票价的箱线图然后对超过上边缘Q31.5倍IQR的记录逐个排查而不是一刀切删除——有些高价景区比如带索道和观光车套票的本身定价就高是合理值不是异常值。注意清洗逻辑不要在一开始写得太死先跑一遍探查代码看清楚数据的实际分布再决定哪些规则是必须的哪些反而会把有效信息误伤掉。2.3 派生特征构建让数据更有分析价值原始数据里的信息是“死”的分析的时候需要根据问题场景去构建新特征这一步很容易被新手忽略。这套案例里有几个派生特征我觉得很巧妙价格区间把门票价格离散化成“免费/低价0-50/中价50-150/高价150”四个档位这样后续做等级和类型的交叉分析时比直接用连续数值要直观得多。热度等级把heat列按分位数分为“低热度/中等热度/高热度”三档便于筛选“低调但优质”的景区。地理片区根据城市把四川分为“川西阿坝、甘孜、凉山/川北绵阳、广元、巴中/川南宜宾、泸州、乐山/成都平原成都、德阳、眉山、资阳”几个大片区做区域对比时特别有用。# 价格区间划分示例 bins [-1, 0, 50, 150, float(inf)] labels [免费, 低价, 中价, 高价] df[price_range] pd.cut(df[ticket_price], binsbins, labelslabels)构建派生特征的核心逻辑是“变量的粒度要和你想回答的问题粒度对齐”。如果只是想看“免费景区多不多”用原始价格就够了但如果你想对比“不同片区的消费门槛差异”价格区间这个特征就非常重要。3. 核心分析场景四个维度拆解四川旅游景点数据3.1 地理分布维度哪个市州的景区资源最密集地理分布分析是地域型数据项目的必选项。我用pandas的groupby对城市做了聚合统计算出每个市州的景区数量和5A级景区数量city_stats df.groupby(city).agg( 景区数量(name, count), 5A数量(level, lambda x: (x 5A).sum()), 平均评分(score, mean), 平均票价(ticket_price, mean) ).sort_values(景区数量, ascendingFalse) print(city_stats.head(10))从统计结果看成都市、阿坝州和乐山市的景区数量稳居第一梯队。这个结论本身不意外但结合5A景区的分布后能发现一些有意思的细节阿坝州虽然景区总数不是最多但拥有九寨沟、黄龙、四姑娘山等众多高品质景区5A数量密度非常高而成都的优势在于综合型景区的数量多、类型丰富人文类和城市休闲类占比明显高于川西地区。把经纬度数据结合地图做可视化之后能更清楚地看到四川旅游资源分布的整体格局川西高原地区景区数量少但单个景区体量大、等级高成都平原及周边地区景区密集但以中小型为主川南地区有几个高质量的独立景区但整体集群效应不明显。这种“西高东密”的分布特征对旅游线路设计的参考价值非常直接——川西适合深度游、环线游成都周边适合周末短途游而川南则需要靠主题线路把景区串起来。3.2 景区等级与门票价格维度5A景区一定更贵吗景区等级是个典型的“官方认证”指标和门票价格之间的关系分析起来很有意思。我对不同等级景区的票价分布做了对比结果用箱线图呈现比均值更清楚import matplotlib.pyplot as plt level_order [5A, 4A, 3A, 2A] df_level df[df[level].isin(level_order)] fig, ax plt.subplots(figsize(10, 6)) df_level.boxplot(columnticket_price, bylevel, axax) ax.set_title(不同等级景区门票价格分布对比) plt.show()从箱线图可以直观看到5A景区票价的中位数明显高于4A和3A但更重要的是5A景区的票价波动范围非常大——有完全免费的5A景区部分城市公园类也有票价超过200的“门票观光车索道”综合型景区。这说明“等级”本质上是资源品质和管理的认证和定价之间是弱相关关系实际定价更多取决于景区的运营模式是否依赖门票经济和资源类型。这个分析给到运营侧的启发是如果一个4A景区的票价已经接近甚至超过同区域5A景区的平均水平但评分和热度没有跟上那在游客决策时就会非常被动。反过来对游客来说“低等级高评分”的景区往往是被低估的优质选择后续做旅行推荐时可以从这个切入点挖掘。3.3 游客热度与评分维度叫好和叫座能兼得吗热度和评分是旅游数据的两个核心口碑指标把这两个维度放到一起看可以构建一个经典的四象限分析高热度高评分明星景区、高热度低评分过度商业化景区、低热度高评分宝藏景区、低热度低评分冷门待发展景区。我按照热度指数的中位数和评分的中位数把景区划分到四个象限里然后重点筛选出“低热度高评分”的景区名单median_heat df[heat].median() median_score df[score].median() def classify_quadrant(row): if row[heat] median_heat and row[score] median_score: return 明星景区 elif row[heat] median_heat and row[score] median_score: return 高热度低口碑 elif row[heat] median_heat and row[score] median_score: return 宝藏景区 else: return 冷门景区 df[quadrant] df.apply(classify_quadrant, axis1) treasure df[df[quadrant] 宝藏景区].sort_values(score, ascendingFalse) print(treasure[[name, city, level, score, heat, ticket_price]].head(15))筛选出来的“宝藏景区”名单非常有分析价值。这部分景区往往有几个共同特点位于非核心旅游城市、以自然生态类或小众人文类为主、票价亲民、网络曝光量低但游客口碑扎实。对旅游平台和地方政府来说这类景区是“供给端优化”的重点对象——不需要大改硬件只要补上宣传推广和交通配套就很容易成为下一个增长点。相关性分析也值得做一下。整体来看热度与评分的皮尔逊相关系数在0.3到0.5之间属于中度正相关说明“口碑好的景区通常热度也不会太差”但远达不到“高热度高评分”的程度。这说明旅游市场上的信息不对称还是很明显的——大量游客的景区选择是被流量和营销驱动而不是被真实口碑驱动。3.4 景区类型维度自然山水和人文古迹的消费差异四川的景区类型分布非常丰富我把标签归并成三类自然景观类山岳、湖泊、森林、草原、人文历史类古镇、博物馆、寺庙、遗址和综合度假类度假区、主题乐园。这三类景区的游客消费行为差异很大。统计分析显示自然景观类的平均门票价格最高景区体量也最大游客游玩时长普遍在一天以上二次消费观光车、索道、餐饮占比较高人文历史类的门票价格相对亲民但游客的复游率和文化消费讲解、文创有潜力综合度假类的价格区间波动最大热门亲子主题乐园的票价远高于传统景区但口碑分化也最严重。这个维度下还值得做的一个分析是“类型区域”的交叉透视比如拆出“川西的自然景观类景区”和“成都的人文历史类景区”分别看会发现川西自然景区主要靠高客单价的长线游客拉动而成都人文景区的游客更依赖城市休闲流量。同样是四川的景区两个片区的运营逻辑完全不同这比只看全量均值要深刻得多。4. 可视化呈现与业务洞察让分析结果会说话4.1 地图可视化快速建立空间认知空间类数据最忌一张表格丢出来让读者自行脑补。这个案例里用了pyecharts的地理散点图把景区按经纬度标在地图上点的大小映射热度颜色映射景区等级信息密度非常高。from pyecharts import options as opts from pyecharts.charts import Geo geo Geo().add_schema(maptype四川) geo.add( 景区热度, data_pair[(row[name], row[heat]) for row in df.to_dict(records)], type_effectScatter, symbol_size8 ) geo.set_series_opts(label_optsopts.LabelOpts(is_showFalse)) geo.set_global_opts( title_optsopts.TitleOpts(title四川省景区热度分布图), visualmap_optsopts.VisualMapOpts(max_100) ) geo.render(data/output/figures/sichuan_geo_heat.html)地图可视化跑出来之后整个分布格局一目了然热度高的景区集中在川西的九环线沿线、成都周边一小时交通圈和乐山—峨眉山一带而川东北、川南的部分优质景区在地图上明显是“灯下黑”状态。这种空间洞察只用table是得不出来的所以做地域型分析时地图可视化真不是锦上添花就是刚需。4.2 排名对比图与散点四象限图除了地图排名类图表是最容易让业务方看懂的形式。我用条形图展示每个市州的景区数量和平均评分Top10再用散点图把“热度VS评分”的四象限画出来一个“小明星”和“宝藏”景区识别结果就非常直观了。需要注意一个可视化细节画散点四象限图时最好把每个象限的区域填充成不同颜色并标注出明星景区和宝藏景区里的代表性名字而不是只画一堆点。这样读者不需要自己去对照坐标系一眼就能看出“九寨沟是高热度高评分”“某小众景区是低热度高评分”。可视化的目标永远是降低信息获取成本不是显示你用了多酷炫的图表库。4.3 从数据到结论交叉验证分析假设整个分析做完后我习惯把所有结论放到一张表里做交叉验证。比如“川西景区票价高”这个结论需要同时看片区票价均值、5A景区占比、景区类型分布三组数据来支撑而“宝藏景区集中在非核心城市”的结论需要同时看城市分布、评分排名和热度排名。这套案例的最终产出里附带了一份分析报告摘要结构很简单核心发现、数据支撑、业务建议。每个结论都对应了具体的数据分析过程和图表而不是拍脑袋写出来的。这也是一个特别值得养成的习惯——数据分析的结果如果不落实到“结论证据行动”的结构里就只是一堆图表展示价值会大打折扣。5. 实操中的高频问题与排查技巧5.1 中文编码与字体显示问题数据分析项目里最烦人的不是复杂的算法而是各种“看起来没什么技术含量”的坑。第一个就是中文编码原始CSV用GBK编码保存pandas默认用utf-8读取时直接UnicodeDecodeError。解决方法是读取时指定编码df pd.read_csv(data/raw/sichuan_attractions.csv, encodinggbk, errorsreplace)另外如果用encodingutf-8读进去了但发现中文变成乱码大概率是原文件是GBK且没有正确指定。处理这类问题有个小技巧先用chardet或者notepad打开文件看右下角显示的编码格式再决定用什么编码去读取不要瞎猜。另一个和中文强相关的坑是matplotlib画出的图中文全部变成方框。这是因为matplotlib默认字体不支持中文需要手动设置中文字体import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] plt.rcParams[axes.unicode_minus] False5.2 坐标缺失与地图打点偏移问题景区经纬度数据在地图可视化时如果缺失直接dropna会导致地图上明显少一片区域。我更推荐的做法是用城市平均坐标做近似填充但如果一个城市只有一两个景区且有坐标缺失误差会很大这时候宁可删除也不要硬填。还有个容易踩的坑是“坐标系不一致”部分数据源给的是GCJ-02火星坐标坐标系地图组件默认预期WGS-84坐标如果不做转换会发现所有点都偏移了几百米到几公里。如果是做省域级别的宏观分布分析这个偏移量可以容忍但如果要精确到乡镇级别就必须做坐标纠偏。常见的做法是用coord_convert类库或在线接口做批量转换。5.3 数据源可靠性分析怎么判断数据有没有代表性拿到这份数据集时我专门做了外部验证。简单来说就是用四川省文旅厅公开的A级景区名录和这份数据进行比对确认覆盖率和字段准确度。真实项目中这个步骤非常有必要数据如果本身不靠谱后面分析得再漂亮也是空中楼阁。验证方法主要有几个抽样检查景区名称的准确性有没有不存在的景区被混了进来检查各市州景区数量占比是否和官方统计大体一致还有交叉核对重点景区的门票价格和官方渠道是否对得上。这套数据我抽查下来整体准确率是可以接受的大部分核心景区的名称、等级、坐标都对得上适合作为学习分析的样本数据。5.4 代码复现与扩展方向这套案例的代码在基础的Python环境上直接就能跑通依赖库只有pandas、matplotlib、pyecharts这几样安装起来很简单不需要上大集群。如果你自己复现建议按我前面说的目录结构把原始数据和输出文件分开放保持整个项目的整洁避免后续迭代时找不到文件。代码本身的风格也比较清晰函数式封装为主。比如清洗逻辑写成了clean_data(df)可视化逻辑写成了plot_geo_map(df, output_path)后面想加分析需求只要写好新的函数然后在主流程里调用就行不用把大段逻辑堆在notebook里面。扩展方向就更多了可以接入时间维度的游客量数据做季节性分析可以爬取OTA平台评论做NLP情感分析可以结合交通数据做可达性分析。只要字段设计合理这套框架可以一直往里加东西。我个人在实际跑这套数据的时候最大的体会是“字段设计决定分析上限”——这份数据集之所以能做出这么多维度的分析核心不是代码写得多好而是前期的字段规划足够完整。你在自己的项目里如果只能从零开始做一件事那我强烈建议把时间和精力优先投入在数据采集的字段设计上哪怕少采集一些景区数量也要保证每个景区都有等级、坐标、票价、评分和热度这些关键字段。数据底座打好了后面怎么分析都顺手。本文还有配套的精品资源点击获取