资讯动态

网易云歌单数据分析:pandas清洗与pyecharts可视化实战

发布时间:2026/9/20 9:53:12 来源:尧图企业网站定制
简介数据分析的核心在于从原始数据中提取有效信息而数据清洗与可视化是其中关键环节。利用pandas可高效完成类型转换、去重与字段拆分保证数据质量借助pyecharts能快速生成交互式图表直观呈现分布规律。在课程设计、期末大作业等工程实践中如何基于真实数据集完成从清洗到展示的完整流程是学习者经常面临的挑战。以网易云歌单为具体案例通过字段建模、pandas预处理、多维统计与pyecharts可视化配置完整呈现了播放量分布、标签聚合及收藏相关性分析。该案例覆盖数据分析全流程为理解数据建模与可视化设计提供了可复用的实践参考。1. 为什么拿网易云歌单当数据分析案例期末大作业选网易云歌单做分析起因很直接要找一个不依赖复杂爬虫、仍有分析层次的数据集。歌单自带播放量、收藏量、歌曲数和创建者标签既能做统计也能做可视化正好覆盖 Python 数据分析与可视化大作业的 pandas、pyecharts 技术栈。整套源码按清洗、统计、可视化、汇总四步组织跑通后输出一份可逐页浏览的 HTML 报告适合课程设计与期末答辩。对熟手来说标签与播放量之间的关系也值得细看。下面从清洗阶段的字段设计讲起再到统计口径和图表配置最后收在运行环境与排版细节上。2. 歌单数据建模与清洗字段设计到 pandas 预处理2.1 歌单数据的字段选择与存储结构这个项目里不直接抓全量歌单而是把网易云歌单接口返回的 JSON 快照先落成本地文件再用 Python 二次整理。常见做法是保存四个核心字段歌单 id、歌单名称、歌曲数量、播放量再加上收藏量与标签。字段不是越多越好课程设计里字段过多反而让后续可视化没有重点答辩时也容易讲散。字段类型来源用途playlist_idint歌单唯一编号去重、排序namestr歌单名称展示与检索track_countint歌曲数量计算曲目区间play_countint播放次数核心统计指标book_countint收藏次数相关性分析tagslist歌单标签分类聚合存储上我一般保留两层原始 JSON 和清洗后的 CSV。JSON 是证据CSV 是分析素材后面跑统计全部读 CSV避免每次重复处理原始文件。README 里也建议按这个结构组织数据目录评阅时一眼就能看出数据流。2.2 用 pandas 完成类型转换与去重接口拿下来的字段多半是字符串play_count 可能是 123456tags 可能是 华语,流行,伤感。先用 pandas 读入再做统一清洗。import pandas as pd df pd.read_json(data/playlist_raw.json) # 只保留需要的列避免后续视角被无关字段干扰 df df[[playlist_id, name, track_count, play_count, book_count, tags]] # 播放量、收藏量转成数值型错误值统一处理为 0 for col in [play_count, book_count, track_count]: df[col] pd.to_numeric(df[col], errorscoerce).fillna(0).astype(int) # 同一歌单可能被抓取多次按 id 去重并保留第一次出现 df df.drop_duplicates(subsetplaylist_id, keepfirst) # 清洗名称两端空格去除全空行 df[name] df[name].str.strip() df df[df[name].notna() (df[play_count] 0)]errorscoerce的作用是把无法解析的脏数据变成NaN再通过fillna(0)兜底这一步很关键如果直接用astype(int)强转遇到空字符串会直接抛异常。drop_duplicates用歌单 id 做唯一键保留第一次抓取的结果保证后面统计的样本不重复。过滤条件play_count 0能去掉那些拿接口测试生成的空歌单让统计结果更贴近真实场景。2.2.1 标签字段的拆分处理tags在 JSON 里是列表但有时读入后变成了字符串。统一判断类型后拆开import ast def safe_split_tags(value): if isinstance(value, str): try: return ast.literal_eval(value) except (ValueError, SyntaxError): return [value] return value df[tags] df[tags].apply(safe_split_tags) # 取第一个标签作为主标签空标签补其他 df[main_tag] df[tags].apply(lambda x: x[0] if x else 其他)ast.literal_eval比eval安全它只解析字面量结构不会执行表达式。拆出第一个标签作为“主标签”方便后面画饼图时聚合避免一个歌单被分到多个分类导致占比总和超过 100%。标签个数多时更适合放到词云里做全局展示不参与分类统计。这样清洗完后样本量大概会减到原来的八成甚至更少但留下来的每一条都能对上明确的统计口径后续画图不会因为脏数据出现莫名其妙的断档。3. 统计维度拆解排序、分组聚合与指标计算3.1 播放量分布与 TOP 排行清洗完数据后第一件事看整体分布。歌单播放量是典型的右偏分布少数头部歌单播放量上千万多数歌单只有几百次。这个分布本身就适合作为分析报告的开头结论。import numpy as np # 排序后取播放量最高的 15 条歌单 top15 df.nlargest(15, play_count)[[name, play_count, book_count]] # 对数分箱观察分布是否服从长尾 df[play_log10] np.log10(df[play_count] 1) profile df[play_log10].describe()nlargest(15, play_count)内部做了一次部分排序比先sort_values()再head(15)在大样本上更省内存。对数变换np.log10(play_count 1)是为了压缩右侧长尾画直方图的时候区间更清晰不会出现一条柱顶天、其他柱看不见的情况。describe()输出的均值和中位数差距越大说明头部效应越明显。3.2 标签维度的分组聚合可视化项目的常见做法是把主标签按歌单数量聚合找出平台里最热门的音乐场景。tag_stat df.groupby(main_tag).agg( playlist_num(playlist_id, count), avg_play(play_count, mean), total_book(book_count, sum), ).reset_index() tag_stat tag_stat.sort_values(playlist_num, ascendingFalse).head(10)这里用agg一次性算出歌单数量、平均播放量和总收藏量比连续写多个groupby再merge干净很多。playlist_num代表标签覆盖面avg_play等于单位歌单的引流能力两者不一致才值得在答辩时强调。比如“华语”歌单数量大但平均播放一般“助眠”歌单少但单条播放很高对应的运营结论完全不同。3.2.1 播放量与收藏量的相关性检验corr df[[play_count, book_count]].corr(methodpearson) print(corr)如果相关系数大于 0.8说明收藏量和播放量基本同向选一个作为核心指标即可如果小于 0.5说明很多歌单存在“收藏未听”的情况这本身也是一个分析结论。相关系数不用算得很复杂但一定要在报告里写一句因为它们直接决定后面展示哪张图。3.3 歌曲数量的区间切片歌曲数量在统计时按区间切分比看散点更直观。bins [0, 30, 60, 150, 300, 500] df[track_range] pd.cut(df[track_count], binsbins, labels[30, 30-60, 60-150, 150-300, 300]) range_stat df.groupby(track_range, observedTrue).agg( avg_play(play_count, mean), median_play(play_count, median), )pd.cut默认右开区间超过 500 首的会落入 NaN这里用labels显式指定分组名避免出现看不懂的区间编号。observedTrue用来抑制 pandas 2.x 的 FutureWarning也避免空区间在结果里占位。实际跑出来的数据通常显示“60-150 首”这类中等长度歌单的平均播放量更高原因是太短的歌单内容单薄太长的歌单用户有疲劳这个规律可以写进报告当作核心发现。4. 可视化模块设计与 pyecharts 参数配置4.1 图表选型与展示链路这个项目的可视化部分我一般用 pyecharts 做原因是渲染出来是 HTML可以直接交给浏览器数据与界面分离答辩时现场换数据重跑也方便。图表选型遵循一个原则类别对比用柱状图占比结构用饼图分布用直方图文本强调用词云。分析目标图表pyecharts 类数据字段播放量 TOP 歌单横向柱状图Barname, play_count标签结构占比环形饼图Piemain_tag, playlist_num播放量分布对数直方图Barplay_log10标签文字强调词云WordCloudtags 全字段双指标对比散点图Scatterplay_count, book_count4.2 柱状图与散点图的配置参数下面这段代码对应播放量 TOP 歌单from pyecharts import options as opts from pyecharts.charts import Bar bar ( Bar(init_optsopts.InitOpts(width1200px, height600px)) .add_xaxis(top15[name].tolist()) .add_yaxis(播放量, top15[play_count].tolist(), itemstyle_optsopts.ItemStyleOpts(color#ec4141)) .set_global_opts( title_optsopts.TitleOpts(title播放量 Top15 歌单), yaxis_optsopts.AxisOpts(name播放量), datazoom_opts[opts.DataZoomOpts(range_start0, range_end100)], ) .reversal_axis() ) bar.render(charts/play_top15.html)reversal_axis()把柱状图转成横向歌单名称比较长时横向展示不会截断标签比纵向更利于对比阅读。datazoom_opts加上后可以在 HTML 里拖拽缩放答辩演示时引导操作感更强去掉它页面更简洁数据量小的时候没必要加。颜色#ec4141与网易云品牌色保持一致整个报告的图表视觉上会更统一。播放量与收藏量的双指标对比用散点图from pyecharts.charts import Scatter scatter ( Scatter(init_optsopts.InitOpts(width900px, height600px)) .add_xaxis(df[play_count].tolist()) .add_yaxis(收藏量, df[book_count].tolist(), label_optsopts.LabelOpts(is_showFalse)) .set_global_opts( title_optsopts.TitleOpts(title播放量-收藏量散点分布), xaxis_optsopts.AxisOpts(name播放量, type_log), yaxis_optsopts.AxisOpts(name收藏量), ) )type_log把 X 轴设为对数刻度能有效摊开长尾分布避免所有点挤在左下角。label_opts.is_showFalse关闭数据点标签真实数据点数量多时开启标签会把图面完全盖住。4.3 词云的生成与中文字体词云图不在 pyecharts 主体包里我一般用wordcloud库先生成 PNG再插入 HTML避免依赖浏览器内核渲染导致白屏。from wordcloud import WordCloud # tags 是多值字段explode 展开成每行单个标签再拼接 all_tags df[tags].explode().astype(str).tolist() word_freq dict(pd.Series(all_tags).value_counts()) wc WordCloud( font_pathC:/Windows/Fonts/simhei.ttf, width1000, height600, background_colorwhite, ) wc.generate_from_frequencies(word_freq) wc.to_file(charts/tag_wordcloud.png)astype(str)是防御性写法防止个别行为 NaN 时 explode 报错。font_path必须指定中文字体否则词云里的中文全部显示为方框这是最容易扣分的坑。图片生成后用 HTML 里相对路径嵌入即可不需要再走 pyecharts 的 render。5. 代码组织与运行环境从源码到可演示系统5.1 目录结构与调用链源码解压后大概是这样的结构NeteaseCloudMusicDataAnalysis/ ├── data/ │ ├── playlist_raw.json │ └── playlist_clean.csv ├── src/ │ ├── data_clean.py │ ├── stats_calc.py │ ├── chart_render.py │ └── main.py ├── charts/ ├── report/ └── README.mdmain.py依次调用清洗、统计、绘图三个模块保证任意一步出错只影响单个环节。data/playlist_clean.csv是中间产物重复运行时不重读 JSON节省时间。# src/main.py from data_clean import load_clean from stats_calc import run_stats from chart_render import render_all if __name__ __main__: df load_clean(data/playlist_raw.json) stat run_stats(df) render_all(df, stat) print(analysis finished, open report/index.html)模块之间通过 DataFrame 传递数据不用落盘中间文件减少磁盘 I/O。if __name__ __main__的写法让模块既能被 import 也能被直接执行便于在 Jupyter 里单步调试某个环节。5.2 Python 环境与依赖的安装顺序项目依赖集中在 pandas、pyecharts、wordcloud 三个库。新环境安装时建议固定版本避免 pyecharts 大版本升级导致 API 变化。pip install pandas pyecharts wordcloud pip freeze requirements.txt注意 Python 3.10 以上的环境里wordcloud 需要预编译的 wheel 包如果安装报错优先尝试pip install wordcloud --only-binary :all:强制使用二进制发布。pyecharts 在 2.x 之后接口较稳定但InitOpts里的theme参数如果写错只在渲染时出现样式回退代码层面不会拦截排查时注意看生成的 HTML 图表配色是否符合预期。5.2.1 字体与路径检查生成的 HTML 直接双击打开即可不需要启动服务器。如果图表数据量大导致首屏卡顿更合理的做法是给柱状图加datazoom而不是减少样本。词云字体路径缺失时运行前检查import os font_path C:/Windows/Fonts/simhei.ttf assert os.path.exists(font_path), 字体缺失请修改 font_path注意Linux 环境没有simhei.ttf需要先安装fonts-wqy-microhei或把字体文件放进项目目录并在WordCloud(font_path...)里改为相对路径。5.3 文档与答辩素材的组织README 需要写清楚三件事数据来源与获取时间、运行环境及操作命令、输出文件说明。课程设计材料一般还要求一份项目报告把“为什么选这个数据集”“可视化方案怎么定”“发现了什么”三段写清源码目录与报告目录一一对应评阅时按图索骥不会因为找不到文件而卡流程。源码里已有的注释也是评分点重点函数头用 docstring 说明入参和返回值比满屏#更受用。6. 让分析图拿得出手的三个细节6.1 长文本标签的旋转与裁切横向柱状图解决了歌单名称过长的问题但保存成 HTML 后部分浏览器对过长的图例仍会压缩换行。把柱状图的label_opts做一层保护bar.set_series_opts( label_optsopts.LabelOpts( rotate15, overflowtruncate, width120, ) )overflowtruncate在文字超出width时省略号收尾rotate15让斜排的标签不至于互相重叠。注意rotate只对横向柱状图有意义饼图里的标签用formatter控制更合适。6.2 使用同一主题和色板每个图表单独初始化时显式指定同一个主题报告整体观感会提升一个档次。common_init opts.InitOpts(width1100px, height550px, themewalden)pyecharts 内置主题如walden、macarons、infographic风格差异明显。theme参数拼写错误时程序不报错而是回退默认主题所以检查生成的 HTML 时要留意柱体颜色是否一致。所有图表统一InitOpts里的width和height在 PPT 里并排截图时比例一致视觉更整齐。6.3 一键导出 PNG 避免截屏模糊答辩材料里放 HTML 链接不太方便评阅老师通常看 Word 或 PDF 里的截图。用 Selenium 渲染 HTML 后调浏览器截图比手动截屏清晰且能保持统一尺寸from selenium import webdriver driver webdriver.Chrome() driver.get(file:///path/to/report/index.html) element driver.find_element(id, chart_play) element.screenshot(report/play_top15.png) driver.quit()代码里给每个 charts 容器分配一个固定id截图时按id定位保证输出 PNG 与 HTML 中的图表一一对应。没有 ChromeDriver 时会抛出SessionNotCreatedException先核对本机 Chrome 大版本号再下载对应版本的 driver。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价