数据分析学习小结:用pymysql+pandas+matplotlib打通数据全流程
1. 从 MySQL 取数到出图一条能跑通的数据分析入门链路数据分析入门最容易卡住的地方往往不是某个库的语法而是「取数—清洗—聚合—出图」这条链路中间断了一环。你可能跟着教程写完了pymysql.connect结果fetchall()回来一堆元组不知道怎么下手或者 DataFrame 建好了groupby之后列名对不上再或者图画出来了中文全是方块。这篇学习小结就按我自己踩过的顺序把 pymysql 读取 MySQL、pandas 做 DataFrame 清洗聚合、matplotlib 出图这三段拼成一条完整可复制的流程最后给你一个可以持续记录的学习小结模板。先说清楚这套东西是什么、能做什么、适合谁。pymysql 是 Python 连接 MySQL 的驱动负责把 SQL 查询结果拿回本地pandas 的 DataFrame 是带行列索引的二维表格结构负责筛选、打标签、分组、聚合、排序matplotlib 负责把聚合后的结果画成折线图、饼图、柱状图、K 线图。适合刚学完 Python 基础、想用真实数据库数据练手的数据分析入门者也适合需要快速做内部报表原型的同学。整条链路的核心检索词就是 pymysql 取数、pandas DataFrame 清洗聚合、matplotlib 可视化三者缺一不可。我建议你按「先跑通取数、再练 DataFrame、最后接图表」的顺序推进每一步都有可验证的输出。下面从环境准备讲到排错中间所有代码都可以直接复制改连接参数使用。你不需要一次全懂先把第一段跑出len(history_count)的数字信心就来了。2. 前置准备TaoToken 接入与 pymysql/pandas/matplotlib 环境搭建这一节解决两件事一是把模型调用能力接进来方便你在写 SQL 和调 DataFrame 时随时问二是把本地 Python 环境装好。很多入门者卡在环境上所以我把版本和安装命令写全。先说 TaoToken 的接入。它的 API 地址是https://taotoken.net/api官网是https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。你需要在控制台创建 API Key然后把它写进环境变量或配置文件。如果你用的是 Claude Code 这类编码工具可以走 Coding Plan如果只是想验证模型对话效果用模型对话页面即可。接入文档在 doc 页面API Key 管理在 api-keys 页面。注意TaoToken 是合规的模型调用入口不要把它和任何网络加速工具混为一谈。环境这边Python 建议 3.9 以上。安装三个核心库pip install pymysql pandas matplotlib如果你还要处理 K 线里的高精度小数标准库decimal就够了不用额外装。验证安装python -c import pymysql, pandas, matplotlib; print(pymysql.__version__, pandas.__version__, matplotlib.__version__)能打印出三个版本号就说明环境 OK。接下来准备一个测试库。我用的是本地 MySQL建一张history_count表存历年人口变化字段有year, total, man, woman, city, village再建一张age_count表存按年龄人口统计字段有area, age0_14, age15_59, age60, age65。建表语句CREATE TABLE history_count ( year INT, total DECIMAL(10,2), man DECIMAL(10,2), woman DECIMAL(10,2), city DECIMAL(10,2), village DECIMAL(10,2) ); CREATE TABLE age_count ( area VARCHAR(32), age0_14 DECIMAL(10,2), age15_59 DECIMAL(10,2), age60 DECIMAL(10,2), age65 DECIMAL(10,2) );插入几条测试数据后用命令行mysql -u root -p能select * from age_count;看到结果就说明数据库侧没问题。这一步别跳过后面报错排查时你会感谢自己先确认了数据源。关于模型接入的配置文件如果你用支持 OpenAI 兼容协议的工具可以写一个settings.json或config.toml。以通用 JSON 为例{ base_url: https://taotoken.net/api, api_key: sk-你的Key, model: claude-sonnet-4-20250514 }三件套就是 Base URL、Key、Model ID缺一个都连不上。写 SQL 遇到不确定的聚合写法时直接把表结构和需求丢给模型让它给一版 SQL你再回数据库验证这个循环对入门者特别高效。3. 可复制配置pymysql 连接、DataFrame 清洗聚合与 matplotlib 出图脚本这一节是全文的核心给你三段可直接复制的代码。第一段负责取数第二段负责清洗聚合第三段负责出图。我按「连接配置—取数—建 DataFrame—清洗—聚合—画图」的顺序组织。先看连接配置。关键点是cursorclasscursors.DictCursor它让fetchall()返回带字段名的字典列表而不是元组列表这样DataFrame()一建就有列名省掉手动指定 columns 的麻烦。# coding: utf-8 import pymysql as mysql from pymysql import cursors from pandas import DataFrame import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [Microsoft YaHei] plt.rcParams[axes.unicode_minus] False conn mysql.connect( host192.168.0.3, port3306, userjiker-coding, passwdjiker-coding-Pwd-1234, dbcoding, charsetutf8, cursorclasscursors.DictCursor ) def fetch(sql): cursor conn.cursor() cursor.execute(sql) rows cursor.fetchall() cursor.close() return rows history_count fetch(select year,total,man,woman,city,village from coding.history_count order by year) age_count fetch(select area,age0_14,age15_59,age60,age65 from coding.age_count order by area) print([取数] history_count , len(history_count), age_count , len(age_count))跑通这段你会看到两个长度数字。如果报Access denied检查 user/passwd如果报Unknown database检查 db 名。第二段是 DataFrame 清洗聚合。把字典列表转成 DataFrame然后做删列、加列、求均值、分组、排序。df_history_count DataFrame(history_count) df_age_count DataFrame(age_count) # 去掉 area 列后按列求平均得到各年龄段占比 df_age_group df_age_count.drop(area, axis1, inplaceFalse) df_age_group[age60_65] df_age_group[age60] - df_age_group[age65] df_age_group df_age_group.mean() del df_age_group[age60] print(df_age_group)这里drop(..., inplaceFalse)返回新对象不动原表mean()默认按列求平均del删掉不需要的列。如果你要按发卡机构统计交易用groupby().agg()df_trade DataFrame(trade_infos) result df_trade.groupby(ISS_INS_ID_CD).agg({TRANS_ST: count, TRANS_AT: sum}) result result.sort_values([TRANS_ST], ascendingFalse).head(10)逾期概率统计用打标签加分组df_bad DataFrame(bad_loan_infos) total_num len(df_bad) overtime df_bad[df_bad[past_due_days] 0] overtime.loc[(overtime.age 18) (overtime.age 25), AgeGroup] 18-25 overtime.loc[(overtime.age 26) (overtime.age 30), AgeGroup] 26-30 overtime.loc[(overtime.age 31) (overtime.age 40), AgeGroup] 31-40 overtime.loc[(overtime.age 41), AgeGroup] 41 age overtime[[AgeGroup, loan_id]].groupby(AgeGroup).agg(count)第三段出图。折线图看趋势饼图看占比柱状图看排名。fig, axes plt.subplots(1, 2, figsize(12, 5)) axes[0].plot(df_history_count[year], df_history_count[total], markero) axes[0].set_title(历年人口变化) axes[0].set_xlabel(年份); axes[0].set_ylabel(总人口) axes[1].pie(df_age_group.values, labelsdf_age_group.index, autopct%1.1f%%) axes[1].set_title(各年龄段占比) plt.tight_layout() plt.savefig(summary.png, dpi120) plt.show()K 线大阳线判断用decimal.Decimal保证精度import decimal df_k DataFrame(stock_klines) df_k[big_yang] 0 df_k[wave_range] 0 df_k.loc[df_k[yclose] 0, yclose] df_k.loc[df_k[yclose] 0][close] df_k[wave_range] (df_k[close] - df_k[yclose]) / df_k[yclose] * decimal.Decimal(100.0) df_k.loc[(df_k[wave_range] 1.5) (df_k[close] df_k[open]), big_yang] 1房价增长率排序df_house DataFrame(house_prices) df_house[wave_range] pd.to_numeric( (df_house[end_price] - df_house[start_price]) / df_house[start_price] * decimal.Decimal(100.0), errorscoerce) df_house df_house.sort_values(by[wave_range], ascending[False]) df_house df_house.round({wave_range: 2})to_numeric把结果转数字errorscoerce把转不了的变 NaNround保留两位。这几段拼起来就是完整链路。4. 验证请求与成功结果逐步确认每一步的输出写完代码不验证等于没写。这一节给你一套逐步验证动作每步都有预期输出。第一步验证数据库连接。执行print(conn.open)返回True说明连接活着。如果返回False说明连接已断检查网络和 MySQL 服务。第二步验证取数条数。print(len(history_count), len(age_count))正常应该打印出两张表的行数比如30 31。如果打印0 0说明表里没数据或 SQL 条件过滤掉了。第三步验证 DataFrame 结构。print(df_age_count.head())你应该看到带列名的表格area age0_14 age15_59 age60 age65 0 上海 9.80 66.82 23.38 16.28 1 云南 19.57 65.52 14.91 10.75如果列名是0 1 2 3 4说明你忘了DictCursorfetchall()返回的是元组。第四步验证聚合结果。print(df_age_group)应该看到各年龄段均值且age60_65是age60 - age65的结果。如果报KeyError: age60_65检查加列那行是否在mean()之前执行。第五步验证图表文件。运行出图脚本后当前目录应该生成summary.png。用ls -lh summary.png看文件大小正常几十到几百 KB。打开图片中文标题正常显示、负号正常显示就说明rcParams配置生效。第六步验证模型接入。如果你用 TaoToken 的模型对话验证 SQL 写法发一句「帮我写一个按年份分组求 total 均值的 SQL」能正常返回就说明 Base URL、Key、Model ID 三件套配置正确。这一步和数据分析链路是并行的用来加速你写 SQL 和调 DataFrame。把这六步的输出记进你的学习小结模板格式建议步骤命令/代码预期输出实际输出是否通过连接conn.openTrue取数len(history_count)0结构df.head()带列名聚合df_age_group均值出图summary.png文件存在这个表格本身就是很好的学习记录下次遇到问题直接翻表。5. 本篇常见报错排查401、local proxy failed、reading choices、OAuth入门阶段报错集中在连接、鉴权、数据结构和模型接入四类。我按真实报错逐条给排查路径。pymysql.err.OperationalError: (1045, Access denied for user ...)。这是账号密码错。检查user和passwd是否和 MySQL 里一致注意密码里的特殊字符。如果确认没错可能是该用户没有从当前主机连接的权限用select user, host from mysql.user;看 host 是不是%。pymysql.err.OperationalError: (2003, Cant connect to MySQL server on ...)。这是连不上服务。先ping主机再telnet 192.168.0.3 3306看端口通不通。端口不通多半是 MySQL 没启动或防火墙拦了。KeyError: ISS_INS_ID_CD。这是列名对不上。print(df_trade.columns)看实际列名可能是大小写或空格问题。用df_trade.columns df_trade.columns.str.strip()去空格。ValueError: could not convert string to float。这是to_numeric遇到非数字。加errorscoerce把脏数据变 NaN再df.dropna()或fillna(0)。模型接入侧401 Unauthorized最常见。检查 API Key 是否复制完整、有没有多余空格、是否过期。Base URL 要写https://taotoken.net/api不要漏掉/api。如果报local proxy failed说明你本地配了代理但代理没起来检查环境变量HTTP_PROXY/HTTPS_PROXY临时unset掉再试。如果报reading choices或返回结构里没有choices字段多半是模型 ID 写错或该模型不支持当前接口换成文档里列出的 Model ID。OAuth相关报错通常出现在 Claude Code 这类工具检查登录态是否过期重新走一遍授权流程或者改用 API Key 方式接入。还有一个隐蔽的坑matplotlib中文显示方块。确认plt.rcParams[font.sans-serif] [Microsoft YaHei]在import之后、画图之前设置Linux 上可能没有雅黑换成SimHei或WenQuanYi Micro Hei。负号显示异常就加plt.rcParams[axes.unicode_minus] False。排查顺序建议先确认数据源再确认数据结构最后确认图表配置。模型接入报错单独排查不要和数据库报错混在一起看。6. 把链路固化成学习小结模板持续记录与下一步跑通一次不算会能重复跑通才算。我建议你把上面的流程固化成一个小结模板每次练新数据集时套用。模板分四块数据源信息、取数 SQL、DataFrame 操作记录、图表输出。数据源信息记 host、port、db、表名取数 SQL 记完整语句和返回条数DataFrame 操作记每一步的输入输出形状比如df.shape从(31, 5)变成(31, 4)图表输出记文件名和结论。下一步可以练的方向把fetch函数改成带参数的避免 SQL 注入用pd.read_sql直接读省掉手动建 DataFrame把多个图拼成子图把结果导出 Excel 做汇报。每练一个点就在模板里加一行记录。如果你在写 SQL 或调 DataFrame 时想快速验证思路可以用 TaoToken 的模型对话页面问一版写法再回本地跑长期做编码和 Agent 类任务可以看 Coding Plan接入配置和 Key 管理分别在接入文档和 API Keys 页面。把这条链路跑顺你的数据分析学习小结就不再是零散笔记而是一套能复用的工作流。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →