
简介这份资源面向希望系统掌握Python数据分析与可视化的学习者覆盖从编程基础到实战项目的完整技能链路适合高校学生、转行者及需要处理结构化数据的从业者。压缩包共162个文件约31.27MB以67个ipynb实验代码、11个pptx课件、10个csv与6个xls数据集为主辅以tif、jpg图表素材及doc、pdf教学文档兼顾理论讲解与动手实践。内容从数据分析与可视化概述切入依次讲解Python编程基础、Pandas统计分析、数据载入与预处理再深入Matplotlib、Seaborn绘图及pyecharts交互式图表并配套iris、红酒品质、学生成绩等真实数据集供练习。已有18154人学习下载读者可借助课件与源码复现数据清洗、统计分析与多库可视化全流程积累可迁移的项目经验。1. 从一份能跑的数据分析源码说起为什么我建议你从拆项目开始学很多人学 Python 数据分析卡在同一个地方pandas 的 API 背了一堆matplotlib 的参数也查了不少但真给一份 CSV还是不知道从哪下手。问题不在语法在于你从来没有完整地跑通过一个真实项目。这份「Python 数据分析与可视化」源码包就是冲着这个痛点来的——它把数据读取、清洗、统计分析、可视化出图串成了一条完整链路每个环节都有可运行的代码不是零散的知识点拼盘。适合谁刚学完 pandas 基础想找个练手项目的或者工作中需要快速搭一套数据分析脚本、不想从零造轮子的开发者。你拿到手就能跑跑完就能改改完就能用到自己的数据上。2. 项目结构拆解从数据文件到图表输出的完整目录2.1 目录布局与模块职责拿到源码包第一件事不是急着跑而是先看目录结构。这个项目的组织方式很典型适合作为数据分析类项目的模板来理解。常见做法是按功能分层大致长这样data_analysis_project/ ├── data/ # 原始数据与清洗后数据 │ ├── raw/ # 原始 CSV、Excel 文件 │ └── processed/ # 清洗后的中间数据 ├── src/ # 核心代码 │ ├── data_loader.py # 数据读取与初步检查 │ ├── data_cleaner.py # 缺失值、异常值、类型转换 │ ├── analyzer.py # 统计分析与聚合计算 │ └── visualizer.py # 图表绘制与导出 ├── output/ # 图表、报告输出目录 │ ├── figures/ # PNG、HTML 图表 │ └── reports/ # 导出的统计结果 ├── config.py # 路径、参数、常量配置 ├── main.py # 主流程入口 └── requirements.txt # 依赖清单这个结构的好处是职责清晰data_loader只管读进来data_cleaner只管洗干净analyzer只管算visualizer只管画。你改任何一个环节不会牵连其他模块。我一般会建议新手先把main.py从头到尾读一遍看清楚数据是怎么从data/raw流到output/figures的这条链路理解了整个项目就通了。2.2 依赖清单与运行环境requirements.txt里通常包含这几个核心库pandas做数据处理numpy做数值计算matplotlib和seaborn做静态图表plotly做交互式图表。版本方面pandas 建议 1.5 以上matplotlib 3.5 以上避免一些旧版本的 API 兼容问题。安装依赖的命令很直接# 创建虚拟环境推荐避免污染全局包 python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate # 安装依赖 pip install -r requirements.txt这里有个细节值得注意如果你用的是 macOS 的 M 系列芯片某些旧版本的 numpy 可能需要 Rosetta 才能装直接pip install报错的话先升级 pip 再试。另外plotly如果只是导出静态图片还需要额外装kaleido这个在 requirements 里不一定有跑的时候报错再补装就行。2.3 配置文件的设计思路config.py这个文件容易被忽略但它决定了项目能不能灵活复用到你自己的数据上。典型内容长这样# config.py - 全局配置 import os # 基础路径 BASE_DIR os.path.dirname(os.path.abspath(__file__)) DATA_RAW_DIR os.path.join(BASE_DIR, data, raw) DATA_PROCESSED_DIR os.path.join(BASE_DIR, data, processed) OUTPUT_FIGURES_DIR os.path.join(BASE_DIR, output, figures) OUTPUT_REPORTS_DIR os.path.join(BASE_DIR, output, reports) # 数据文件配置 RAW_DATA_FILE sales_data.csv # 原始数据文件名 ENCODING utf-8 # 文件编码中文数据常用 gbk DATE_COLUMNS [order_date, ship_date] # 需要解析为日期的列 # 可视化配置 FIGURE_DPI 150 # 图片分辨率 FIGURE_SIZE (12, 6) # 默认画布尺寸 COLOR_PALETTE viridis # 配色方案把路径和参数抽到配置文件里好处是你换一份数据只需要改RAW_DATA_FILE和DATE_COLUMNS不用去翻每个模块的代码。我见过太多人把路径硬编码在函数里换个环境就跑不起来这种坑提前避开。3. 核心模块逐段拆数据读取、清洗、分析与可视化3.1 数据读取与初步体检data_loader.py是整个流程的入口它的任务不只是pd.read_csv()一行搞定还要做初步的数据体检。常见写法# src/data_loader.py import pandas as pd import config def load_data(file_pathNone): 读取原始数据返回 DataFrame if file_path is None: file_path f{config.DATA_RAW_DIR}/{config.RAW_DATA_FILE} # 读取 CSV指定编码 df pd.read_csv(file_path, encodingconfig.ENCODING) # 日期列自动解析 for col in config.DATE_COLUMNS: if col in df.columns: df[col] pd.to_datetime(df[col], errorscoerce) return df def inspect_data(df): 数据体检形状、类型、缺失、重复 print(f数据形状: {df.shape}) print(f\n列类型:\n{df.dtypes}) print(f\n缺失值统计:\n{df.isnull().sum()}) print(f\n重复行数: {df.duplicated().sum()}) print(f\n前5行预览:\n{df.head()}) return { shape: df.shape, missing: df.isnull().sum().to_dict(), duplicates: df.duplicated().sum() }这段代码的关键点pd.to_datetime加了errorscoerce遇到无法解析的日期不会直接报错而是转成NaT后续清洗时统一处理。inspect_data返回一个字典方便在main.py里做判断——比如缺失率超过 50% 的列可能直接考虑丢弃。参数说明encoding这个参数很关键中文数据用utf-8读出来乱码的话换成gbk或gb18030试试。DATE_COLUMNS在 config 里配置不同数据集的日期列名不一样改配置就行。3.2 数据清洗缺失值、异常值与类型转换data_cleaner.py是工作量最大的模块也是最能体现分析水平的地方。清洗策略没有标准答案取决于业务场景。常见做法# src/data_cleaner.py import pandas as pd import numpy as np def handle_missing(df, strategyauto): 缺失值处理 df_clean df.copy() for col in df_clean.columns: missing_rate df_clean[col].isnull().mean() if missing_rate 0: continue elif missing_rate 0.5: # 缺失超过一半直接丢弃该列 df_clean.drop(columns[col], inplaceTrue) print(f丢弃列 {col}缺失率 {missing_rate:.2%}) elif df_clean[col].dtype in [float64, int64]: # 数值列用中位数填充 median_val df_clean[col].median() df_clean[col].fillna(median_val, inplaceTrue) else: # 类别列用众数填充 mode_val df_clean[col].mode()[0] df_clean[col].fillna(mode_val, inplaceTrue) return df_clean def remove_outliers(df, columns, methodiqr): 异常值处理IQR 法 df_clean df.copy() for col in columns: if method iqr: Q1 df_clean[col].quantile(0.25) Q3 df_clean[col].quantile(0.75) IQR Q3 - Q1 lower Q1 - 1.5 * IQR upper Q3 1.5 * IQR # 用边界值截断而不是直接删除 df_clean[col] df_clean[col].clip(lower, upper) return df_clean逻辑说明缺失值处理分三种情况——缺失率过高直接丢列数值列用中位数填充比均值更抗异常值类别列用众数填充。异常值处理用 IQR 法但注意这里用的是clip截断而不是删除行因为删除行可能导致样本量骤减截断保留了样本但限制了极端值的影响。参数说明strategyauto是预留的扩展点你可以改成drop直接删缺失行或者interpolate做插值。columns参数指定对哪些列做异常值处理不是所有数值列都需要比如 ID 列就不需要。3.3 统计分析分组聚合与透视表analyzer.py负责从清洗后的数据里提取业务洞察。最常用的两个工具是groupby和pivot_table# src/analyzer.py import pandas as pd def group_summary(df, group_col, value_col, agg_funcsNone): 分组聚合统计 if agg_funcs is None: agg_funcs [sum, mean, count, std] result df.groupby(group_col)[value_col].agg(agg_funcs) result.columns [f{value_col}_{func} for func in agg_funcs] return result.reset_index() def pivot_analysis(df, index, columns, values, aggfuncsum): 透视表分析 pivot pd.pivot_table( df, indexindex, columnscolumns, valuesvalues, aggfuncaggfunc, fill_value0, marginsTrue, # 添加合计行/列 margins_name合计 ) return pivot def time_series_trend(df, date_col, value_col, freqM): 时间趋势分析 df_ts df.set_index(date_col) trend df_ts[value_col].resample(freq).sum() return trend.reset_index()逻辑说明group_summary一次性输出多个统计量避免反复 groupby。pivot_analysis加了marginsTrue自动算合计fill_value0处理透视后的空值。time_series_trend用resample做时间重采样freqM按月改成W按周Q按季度。参数说明agg_funcs可以自定义比如只关心[sum, mean]就传这个列表。freq参数遵循 pandas 的 offset 别名常用D日、W周、M月、Q季、Y年。3.4 可视化从静态图到交互式图表visualizer.py是最终出成果的地方。这个项目通常同时支持 matplotlib/seaborn 静态图和 plotly 交互图# src/visualizer.py import matplotlib.pyplot as plt import seaborn as sns import plotly.express as px import config # 设置中文字体避免中文乱码 plt.rcParams[font.sans-serif] [SimHei, Arial Unicode MS] plt.rcParams[axes.unicode_minus] False def plot_bar(df, x_col, y_col, title柱状图, saveTrue): 柱状图 fig, ax plt.subplots(figsizeconfig.FIGURE_SIZE) sns.barplot(datadf, xx_col, yy_col, axax, paletteconfig.COLOR_PALETTE) ax.set_title(title, fontsize14) ax.set_xlabel(x_col) ax.set_ylabel(y_col) plt.xticks(rotation45, haright) plt.tight_layout() if save: path f{config.OUTPUT_FIGURES_DIR}/{title}.png plt.savefig(path, dpiconfig.FIGURE_DPI, bbox_inchestight) print(f图表已保存: {path}) plt.close() return fig def plot_interactive_trend(df, date_col, value_col, title趋势图): 交互式趋势图plotly fig px.line( df, xdate_col, yvalue_col, titletitle, markersTrue, templateplotly_white ) fig.update_layout( fontdict(size12), hovermodex unified ) # 导出为 HTML path f{config.OUTPUT_FIGURES_DIR}/{title}.html fig.write_html(path) print(f交互图表已保存: {path}) return fig逻辑说明matplotlib 部分设置了中文字体这是中文数据可视化的必备步骤不设置的话标题和标签全是方块。plot_bar用 seaborn 封装代码更简洁。plot_interactive_trend用 plotly 生成 HTML可以直接在浏览器里缩放、悬停查看数值。参数说明palette控制配色seaborn 支持的方案有viridis、Set2、coolwarm等。bbox_inchestight防止保存时标签被截断。hovermodex unified让悬停时同时显示同一 X 轴上的所有数值。4. 避坑与排查跑这份源码时最容易翻车的几个地方4.1 中文乱码从数据读取到图表显示现象CSV 读进来列名或内容全是乱码或者图表标题显示为方块。原因数据文件编码不是 UTF-8或者 matplotlib 没有配置中文字体。解决读取时指定encodinggbk或encodinggb18030。图表乱码则在visualizer.py开头加plt.rcParams[font.sans-serif] [SimHei]macOS 上换成[Arial Unicode MS]。如果还不行检查系统是否装了对应字体。4.2 日期解析失败导致时间序列断裂现象pd.to_datetime报错或者解析后大量NaT时间趋势图出现断点。原因日期格式不统一比如有的写2024-01-01有的写01/01/2024。解决先用pd.to_datetime(df[col], errorscoerce)强制转换然后检查NaT的比例。如果比例高用format参数指定格式或者写自定义解析函数逐条处理。我一般会先把日期列的前 20 个唯一值打印出来看一眼确认格式再批量转。4.3 内存溢出大文件读取的正确姿势现象读一个几百 MB 的 CSV 直接卡死或报MemoryError。原因默认pd.read_csv会把整个文件加载到内存且自动推断类型可能把整数读成 float64内存翻倍。解决用chunksize分块读取或者指定dtype参数。常见做法是# 分块读取每块 10 万行 chunks pd.read_csv(big_file.csv, chunksize100000) result pd.concat([chunk.groupby(category)[value].sum() for chunk in chunks])另外只读需要的列pd.read_csv(file.csv, usecols[col1, col2])能省不少内存。4.4 图表保存空白或尺寸不对现象plt.savefig()保存出来的图片是空白的或者尺寸和预期不符。原因在plt.show()之后调用savefig此时画布已被清空或者figsize设置后被tight_layout覆盖。解决先savefig再show或者直接用fig.savefig()。尺寸问题检查figsize和dpi的乘积是否合理bbox_inchestight会自动裁剪空白边缘但可能导致尺寸略小于设定值。4.5 plotly 导出静态图片报错现象fig.write_image()报错提示缺少 kaleido。原因plotly 导出 PNG 需要 kaleido 引擎requirements 里不一定包含。解决pip install kaleido。如果还报错检查 plotly 版本旧版本可能需要降级 kaleido。实在不行就导出 HTML用浏览器打开后截图虽然土但管用。5. 二次开发把这套源码改成你自己的分析工具5.1 替换数据源的最小改动路径拿到这份源码后最直接的改造就是换成你自己的数据。改动集中在三个地方config.py里的RAW_DATA_FILE和DATE_COLUMNSdata_cleaner.py里的清洗策略以及analyzer.py里的分组字段和聚合函数。我一般会先跑一遍原始数据看inspect_data的输出根据缺失率和列类型决定清洗方案而不是一上来就套模板。5.2 扩展新的分析维度如果你想加一个同比/环比计算可以在analyzer.py里加一个函数def add_yoy_mom(df, date_col, value_col): 添加同比YoY和环比MoM列 df df.sort_values(date_col).copy() df[MoM] df[value_col].pct_change(periods1) # 环比 df[YoY] df[value_col].pct_change(periods12) # 同比假设月度数据 return df这个函数的periods参数取决于数据频率月度数据同比是 12季度数据是 4日度数据是 365。改的时候注意对齐。5.3 把分析流程封装成命令行工具如果想让非技术同事也能用可以用argparse把main.py包装成命令行工具# main.py 改造示例 import argparse from src.data_loader import load_data, inspect_data from src.data_cleaner import handle_missing, remove_outliers from src.analyzer import group_summary from src.visualizer import plot_bar def main(): parser argparse.ArgumentParser(description数据分析工具) parser.add_argument(--file, typestr, help数据文件路径) parser.add_argument(--group, typestr, defaultcategory, help分组列) parser.add_argument(--value, typestr, defaultamount, help数值列) args parser.parse_args() df load_data(args.file) inspect_data(df) df handle_missing(df) df remove_outliers(df, [args.value]) summary group_summary(df, args.group, args.value) plot_bar(summary, args.group, f{args.value}_sum, title分组汇总) print(summary) if __name__ __main__: main()这样同事只需要跑python main.py --file data/raw/sales.csv --group region --value revenue就能出图不用改代码。5.4 一个我踩过的坑别在清洗阶段丢原始数据最后说一个血泪教训。我早期做数据分析时习惯在handle_missing里直接inplaceTrue修改原始 DataFrame结果后面想换个填充策略重新跑发现原始数据已经被覆盖了只能重新读文件。从那以后我每次做数据清洗都强制走一遍「先 copy 再操作」的流程df_clean df.copy()这行代码从来不省。另外清洗后的数据我会单独存一份到data/processed/而不是每次从原始数据重新跑一遍清洗这样调试分析逻辑时能省不少时间。希望帮到你。本文还有配套的精品资源点击获取