四川旅游景点数据分析实战:从数据清洗到可视化全流程解析
简介数据分析是提取业务价值的核心手段而数据清洗与探索性分析则是保证结论可靠的关键前提。在实际项目中Pandas等Python工具帮助分析师高效处理缺失值、统一字段口径和转换价格区间从而为后续的数据可视化与建模奠定坚实基础。这种技术思路广泛应用于旅游、零售、城市管理等行业。以四川省旅游景点数据为例通过对景区等级、门票价格、游客评分和热度指数进行交叉分析能够揭示旅游资源空间分布、价格与热度的真实关系进而形成有数据支撑的运营建议。围绕一套完整的四川旅游景点分析项目从数据清洗、探索到可视化输出的全过程梳理了实操中的关键步骤与常见坑点为学习者提供可复制的分析框架。 做数据分析这几年一个很深的感受是网上免费的案例教程不少但大多停留在“跑通代码”的层面要么数据集是外国的要么业务场景离我们的生活太远。拿到一份真实、本土化、能直接练手的数据集反而成了稀缺资源。所以当我看到“四川省旅游景点数据分析数据集代码”这个项目标题时第一反应是这东西很适合拿来当完整的数据分析实战样板。这篇文章我会以这套四川省旅游景点数据分析项目为线索把拿到数据集之后从清洗、探索、可视化到结论输出的完整流程拆开讲一遍。重点不是教你怎么背代码而是告诉你拿到一份陌生的景点数据每一步为什么要这么做、踩过哪些坑、怎么判断分析结果靠不靠谱。无论你是正在学Python数据分析的学生还是想转行做数据分析师或者单纯想用数据了解一下四川旅游的底牌这篇都值得认真看完。1. 拿到手的数据到底包含了什么字段含义与数据质量摸底1.1 数据集结构的第一眼判断我打开这份数据集之后先扫了一遍字段名。这类旅游景点数据通常不会太复杂但字段命名往往不太规范需要自己重新理一遍。以这份四川景点数据为例典型的字段包括景点名称、所在城市、景区等级5A/4A/3A等、门票参考价格、用户评分、热度指数、建议游玩时长、景点类型等总共大概四五百条记录覆盖了四川绝大多数A级景区和部分热门非A级景点。第一件事不是急着分析而是用Pandas快速确认数据长什么样。我习惯用info()和head()先看类型和内容而不是直接describe()因为describe()只能给你数值型字段的统计量字符型字段乱不乱、有没有空值得靠info和head来看。import pandas as pd import numpy as np # 读取数据先不指定引擎默认按CSV解析 df pd.read_csv(sichuan_travel_spot.csv, encodingutf-8-sig) print(df.shape) # 看行列数 print(df.info()) # 看字段类型和缺失情况 print(df.head(10)) # 看前10行长什么样这里有个细节数据文件如果是从网上爬下来或者别人整理导出的编码经常是问题。Python里直接读CSV遇到中文乱码多半是编码没对上我一般会先试utf-8报错就换gbk再不行用utf-8-sig。这份数据的编码还算干净但我强烈建议你拿到任何一份数据第一步都先确认编码否则后面全白干。1.2 字段口径不统一的坑看完全部字段之后最需要警惕的是“同一种东西写法不统一”。比如景区等级字段里有的写“5A”有的写“5A级景区”有的写“AAAAA”如果不先统一口径后面做分组统计就会莫名其妙多出几个类别。再比如门票价格字段有的单元格是“免费”有的是“0”有的是“60元”有的是“60-100元”还有的直接空着。“免费”和“0”好处理但“60-100元”这种区间价格就很麻烦你是取60还是100还是取中间值80这里没有标准答案取决于你分析的目的。如果是做价格区间分布可以取区间下限做保守估计如果是算游客花费取平均值更接近实际。我在这份数据里是按区间均值处理的因为后面要拿价格和热度做相关性分析区间均值误差相对可控。清洗这一步我单独强调一下因为太多人忽略它。很多新手拿到数据就直接画图画出来的图表自己都解释不了原因就是底层数据有问题。数据质量决定了分析天花板下面这段代码处理了三个最常见的脏数据问题# 统一景区等级字段 df[景区等级] df[景区等级].str.replace(级景区, ).str.strip() # 把“免费”改为0去掉“元”单位处理区间价格取均值 def parse_price(s): if pd.isna(s): return np.nan s str(s).replace(元, ).strip() if s in [免费, 暂无, -]: return 0 if - in s: parts s.split(-) try: return (float(parts[0]) float(parts[1])) / 2 except: return np.nan try: return float(s) except: return np.nan df[门票价格] df[门票参考价].apply(parse_price)做完这一步再info一次确认没有因为转换产生新的大面积缺失就可以进入真正的探索分析了。2. 景区空间分布与等级梯队四川旅游资源的底牌2.1 按市州聚合看旅游资源的“家底”分布拿到一份省级景点数据集先做空间分布是性价比最高的第一步。四川有21个市州旅游资源分布极不均衡。用groupby按市州统计景区数量再叠加景区等级维度就能非常直观地看出哪些地方是“数量优势”哪些地方是“质量优势”。city_count df.groupby(所在市州)[景点名称].count().sort_values(ascendingFalse) print(city_count) # 等级和市州的交叉表 cross pd.crosstab(df[所在市州], df[景区等级]) print(cross)从结果看成都的景区总量毫无悬念排第一这和成都作为交通枢纽、人口中心、历史文化遗产聚集地等综合因素有关。但真正有意思的是阿坝州和甘孜州景区总数不算最多5A和4A级景区的占比却非常高。这说明这两个地区的旅游资源走的是“精品路线”单个景区的能级很高九寨沟、黄龙、稻城亚丁都集中在这里。这种“数量vs质量”的差异在后面对比分析时特别有用。如果只看景区数量成都碾压一切但如果看高等级景区占比阿坝、甘孜才是四川旅游的天花板。这就是交叉表的威力单一维度看不出这个结论。2.2 等级结构里的“腰部塌陷”问题把所有景区按等级做个柱状图你会看到一个典型的金字塔结构5A级景区的数量很少4A级景区则是绝对主力3A和2A级景区数量也不少。我自己统计下来4A级景区占到了总量的四成以上是四川景区体系的绝对腰部力量。为什么会有这个结构简单说5A级景区的评定标准非常高对服务质量、交通可达性、游客接待能力都有硬性要求不是光有自然资源就能上的。4A级景区门槛相对亲民覆盖面更大所以成了大多数地市州“主推”的景区级别。这个结构给到做旅游数据分析的人一个启发如果你在做游客量预测或者区域旅游经济分析不能只看5A景区4A景区的分布和热度才是基本盘。只盯着头部景区做分析会严重低估很多非传统旅游城市的表现。2.3 用图表呈现空间分布时地图不是首选关于可视化我想多聊两句。很多人一看到“省级景点数据”就下意识想画地图觉得地图直观。但地图类图表有三个问题第一地图底图的坐标数据需要额外找资源网上很多免费的四川省GeoJSON质量参差不齐合并不好反而误导第二景点的分布往往在局部区域高度集中放到省级地图上根本看不清密度差异第三地图图表的颜色分级很容易因为区间设置不当让人产生错误的视觉判断。我在这个项目里更推荐用横向条形图或排序柱状图呈现市州景区数量一眼就能看出梯度差异。如果一定要做地理维度可以用气泡图散点叠加而不是去做完整的省级区域着色。这个判断标准很简单你的分析目的是看“分布结构”还是看“地理拓扑关系”前者用条形图足够后者才需要地图。import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams[font.sans-serif] [SimHei] # 解决中文乱码 plt.figure(figsize(10, 8)) city_count.sort_values().plot(kindbarh, color#4C72B0) plt.title(四川省各市州A级景区数量分布) plt.xlabel(景区数量) plt.tight_layout() plt.savefig(city_spot_count.png, dpi150)这里有一个很隐蔽的坑matplotlib默认字体不包含中文字形直接画图标题和图例里的中文全会变成方框。很多人在这一步就卡住了以为是代码写错了其实是字体问题。用rcParams指定中文字体可以解决SimHei、Microsoft YaHei、Noto Sans CJK都行看你的系统装了哪个。3. 门票价格与热度之间的关系定价值不值得参考3.1 价格数据的描述性统计先看分布形态景区门票价格单独拎出来做描述性统计你会发现中位数和平均数差得很远。这是因为少数高价景区把平均值拉高了大部分景区的门票其实集中在中低价区间。这种数据形态用平均数分析意义不大我更建议做分箱处理。bins [0, 0.1, 50, 100, 200, 500] labels [免费, 0-50元, 50-100元, 100-200元, 200元以上] df[价格区间] pd.cut(df[门票价格], binsbins, labelslabels, rightFalse) price_group df[价格区间].value_counts().sort_index() print(price_group)处理时有个细节市面上很多数据集“免费”和“0”分不清楚有的直接空着。我上面的清洗逻辑里把“免费”改成了0但真实情况中空值可能代表免费也可能代表数据缺失具体怎么处理需要有业务判断。在这个项目里我单独筛了一遍缺失价格的记录发现大部分都是新开发的景区官网没有明确挂牌价所以我保守地选择在相关分析中剔除这些记录而不是强行填0。3.2 价格和热度的相关性结论可能和你想的不一样价格和热度算相关系数我一开始预期是负相关——价格越高去的游客越少热度越低。但实际算出来相关系数只有-0.2左右接近无相关。这说明四川景区的“热度”并不主要由门票价格决定更可能由知名度、交通便利度、社交平台传播效应驱动。为了把这个结论讲清楚我画了一张散点图横轴是门票价格纵轴是热度指数然后按景区等级用颜色区分。结果非常有意思5A景区无论价格高低热度都维持在高位4A景区则分化明显靠近成都的4A景区热度明显高于同等级其他地区的景区3A及以下的景区热度普遍随价格上升而下降。这个现象背后其实是两类景区的逻辑差异头部景区属于“目的地型”游客是先决定去这里再接受价格腰部景区属于“顺路型”游客往往在旅途中临时决定增加行程价格就成了敏感因素。3.3 免费景区真的更受欢迎吗单独把免费景区拎出来看结论更反直觉免费景区的热度两极分化极其严重。一类是城市里的公园、博物馆、历史街区比如成都主城区的一批免费景点热度常年靠前人流量很大另一类是欠发达地区的免费观景台、自然风光点虽然免费但交通不便、配套不完善热度很低。这说明“免费”本身不是流量的保证“可达性”才是。用数据把这个点确认之后对做景区规划的朋友有参考价值一个景区想提升热度定价策略能起的作用有限改善交通接驳、提升周边住宿餐饮配套效果可能更直接。4. 游客体验维度评分和游玩时长背后的问题4.1 评分的分布结构为什么大部分景区都挤在4分以上游客评分是另一个值得深挖的字段。直方图画出来绝大多数景区的评分集中在4.0到4.5之间低于3.5的非常少。这不是四川景区特别优秀而是评分体系本身有偏差愿意在OTA平台打分的人整体偏向正面极端不满意的游客通常直接不发评论。所以我对评分做分析时没有简单看平均值而是看了评分和景区等级的交叉关系。结果发现5A景区的平均评分并没有显著高于4A景区甚至个别5A景区的评分低于某些口碑极好的4A景区。这说明评分更多反映的是“期望管理”而不是“绝对质量”游客对5A景区的期望值更高体验稍有不满意就容易给低分对4A景区期望较低稍有惊喜就容易给高分。4.2 建议游玩时长这个字段暗藏景区定位密码很多数据集里都有“建议游玩时长”字段但大家分析时常常忽略它。我觉得这个字段特别能说明问题因为建议游玩时长直接反映了景区的游览模式。做一次分组分析把景区按建议游玩时长分成“2小时以下”“2-4小时”“4小时以上”三组再对比评分和热度能看出很清晰的规律短时长的景区集中在城市型景点和主题街区游玩节奏快评分普遍不低适合作为行程中的“填空型”景点长时长的景区以自然风光和大型综合度假区为主评分两极分化明显要么因为风景壮丽拿到高分要么因为管理和服务跟不上被吐槽。这个维度对行程规划非常有帮助。如果你是做旅游产品设计的完全可以基于“建议游玩时长”字段搭建一个简易的路线拼接模型把一天的时间拆成上午和下午两个时段分别匹配对应时长的景点再结合地理分布优化动线。4.3 简单文本分析从评论关键词看景区类型风格如果这份数据里还有一段简短的景点描述或游客评论摘要那就可以顺带做一点最基础的文本分析。不需要上什么复杂的NLP模型用jieba分词加词频统计就够了。对高频词做词云或者条形图你会发现不同类型景区的关键词差异非常大。比如自然风光类的高频词是“风景”“栈道”“观景”“徒步”“原始”人文历史类的高频词则是“古迹”“历史”“文化”“寺庙”“博物馆”。这一步虽然简单但能帮你在没有人工标注的情况下快速给景区打一个“类型标签”后续做细分类分析就有抓手了。import jieba from collections import Counter text .join(df[景点简介].dropna().tolist()) words jieba.lcut(text) # 去掉单字和标点等无意义词 stopwords set([的, 了, 是, 在, 和, 有, 与, 及, 等, 、, 。]) words [w for w in words if len(w) 1 and w not in stopwords] counter Counter(words).most_common(30) print(counter)这里有个分词的小坑jieba对景区专有名词的切分不一定准确比如“四姑娘山”可能被切成“四姑娘”和“山”。如果你要精确统计景区名最好在分词前加载自定义词典把已知的景区名称加进去否则统计出来的词频会有偏差。5. 复现这套代码时的几个关键坑我替你踩过了5.1 编码问题不是小事统一用utf-8-sig更稳妥我第一次跑这份数据的时候直接用pandas默认参数读取结果中文列名全部变成乱码。排查了半天发现是编码问题。如果你用记事本打开CSV文件另存时可以选编码优先存成utf-8-sig这样Excel打开不乱码Pandas读取也不乱码。如果用gbk编码存的Pandas读的时候就要指定encodinggbk。一个实用技巧写读取代码的时候别把编码写死先用一个变量定义编码方式后面如果换了数据源只需要改一行。ENCODING utf-8-sig df pd.read_csv(data/sichuan_travel_spot.csv, encodingENCODING)5.2 图表中文乱码的完整解决方案matplotlib画图中文变方块是每个数据分析初学者都会遇到的事。上面我提到用rcParams指定字体但还有个更隐蔽的情况有时候在Jupyter Notebook里设置好了导出成PDF或者在某些Linux服务器上字体又失效了。这是因为你的环境中根本没有对应字体文件rcParams设置了也没用。这时候可以用matplotlib自带的font_manager查一下系统里有哪些中文字体也可以直接下载一个开源中文字体放到系统字体目录。最省事的方案是用Noto Sans CJK开源免费跨平台支持好Linux服务器上装一次基本不会再出问题。5.3 路径别带中文和空格这是最便宜的避坑方式Windows环境下文件路径如果带中文有些库处理起来会出莫名其妙的问题。比如pyecharts渲染地图需要读.js文件路径带中文偶尔会读取失败。我的习惯是建一个纯英文的目录存放数据和代码比如D:/projects/sichuan_analysis/下面分data、code和output三个子目录。这个习惯看起来没什么技术含量但能帮你省掉大量排查时间。5.4 换一份数据怎么复用这套代码把分析流程函数化如果你的目的是学习那跑通一遍就够了。但如果你想把这份代码应用到其他省份的景点数据上我建议你做一件事情把清洗和分析逻辑拆成函数只保留最核心的业务逻辑然后把数据源路径、字段名映射统一放到配置区。这样做的好处是换数据的时候你只需要改配置区的字段映射关系不需要动分析函数。比如原来数据里价格字段叫“门票参考价”新数据里可能叫“票价”通过一个统一的映射字典转换代码的复用性会大幅提升。我在自己项目里的做法是定义了一个标准的DataFrame结构通过rename把外部字段统一映射成内部标准字段后续所有分析都是基于标准字段进行。这一步虽然前期麻烦但换数据源的时候省下的时间绝对值得。6. 从“跑通代码”到“讲好故事”数据分析项目的加分项6.1 能用数据回答的5个问题提前想清楚分析做完之后很多人的报告只是一堆图表的堆砌没有结论。我自己的经验是动手分析之前先列出你真正想回答的问题然后每一个图表都为其中一个问题服务无关的图表不画。以四川旅游景点数据为例我预先列出了5个问题一是四川的景区资源在空间上如何分布二是高等级景区集中在哪里三是门票价格和热度是否相关四是游客评分和景区等级是否一致五是不同地市州的景区特色是什么。整份报告的通篇逻辑就围绕这5个问题展开。6.2 分析结论要有“数据解释建议”三层结构数据分析报告最忌讳的事情是只给结果不给解释比如“成都市景区数量最多”这个结论如果只写到这一句等于什么都没说。合格的写法是再加上“为什么”——成都作为全省交通枢纽和人口中心加上历史文化遗产密度高所以自然成为景区数量第一的城市。然后再给出建议——其他市州在旅游资源开发时如果对标成都核心不在增加景区数量而在提升高等级景区占比和交通可达性。这个三层结构几乎可以套用在任何分析结论上。数据是事实层解释是逻辑层建议是行动层三层都有了才叫一个完整的分析闭环。6.3 用数据讲故事的节奏感从全局到局部从总量到结构最后分享一个我的个人心得一份好的数据分析报告结构上应该遵循“总-分-总”的节奏。先给用户看全局四川21个市州的总量排名再拆解局部头部市州和尾部市州的差异来源最后回到全局形成综合判断四川旅游整体是“成都极点西部资源线”的非均衡结构。这套节奏不是我发明的电影叙事都这么干先介绍背景再铺开冲突最后收束。你写分析报告的时候把自己当成讲故事的人数据是论据结论是剧情读者才会愿意读下去。这也是我在这份四川旅游景点数据分析项目里收获最大的经验分析能力是基础表达能力的差距往往决定你能走多远。本文还有配套的精品资源点击获取