恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

pandas创建DataFrame全攻略:从基础构造到实战清洗

  • 首页
  • 资讯中心
  • /
  • pandas创建DataFrame全攻略:从基础构造到实战清洗

相关资讯

基于Spark的地铁客流分析系统:架构、实践与避坑指南 2026/10/10 11:10:39
Android五子棋课程设计:从棋盘绘制到胜负判定的完整实现 2026/10/10 11:10:39
易物小店微服务架构复盘:SpringBoot+Vue+SpringCloud分布式交换系统实践 2026/10/10 11:05:39

最新资讯

YOLOv8智慧校园人脸识别与公路车辆检测实战指南
SSM求职招聘系统开发全攻略:Java毕设设计与答辩指南
鸿蒙状态管理V2:@Provider与@Consumer跨层级双向同步实践
用JavaCC实现类C编译器:词法、语法、语义与三地址码全解析
Agent-Native模型赛道开卷:基元律动之外还有谁在押注
基于SpringBoot的运动会管理系统:数据建模、并发控制与部署实践

今日推荐

Codex 总用英文回答?从 AGENTS.md 到 config.toml 的中文输出调优指南
OpenClaw 自定义插件开发完整指南(2026最新版):从 TypeScript 到 npm 发布
基于Spark的电影推荐系统全链路实战:从爬虫到Web展示

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

pandas创建DataFrame全攻略:从基础构造到实战清洗

发布时间:2026/10/10 11:10:39
pandas创建DataFrame全攻略:从基础构造到实战清洗 用pandas做数据分析第一步永远是创建DataFrame。很多初学者从教程里抄一段示例代码df pd.DataFrame({name: [张三, 李四], age: [23, 31]})一按回车就觉得自己会了可一旦面对真实场景——订单表里混着千分位金额、日期字段读进来变成字符串、Excel表带两行表头、数据库查出来一堆空值——立刻被各种神秘报错卡住只能到处搜索pandas为什么报KeyErrorDataFrame类型怎么转换这类问题。这篇文章就是一份围绕pandas创建DataFrame的完整实操笔记先把最常用的几种创建方式、示例代码背后的参数逻辑讲透再通过一个电商订单数据的完整案例把从造数据到建表再到清洗成型的整条链路走一遍最后把我在实际项目中反复踩过的坑和排查经验整理成速查表。适合刚接触pandas的Python数据初学者也适合写过一些代码但总在数据结构、类型转换细节上卡壳的同学参考。1. 先想清楚创建DataFrame到底在做什么1.1 DataFrame的本质就是一张会自校正的电子表格理解DataFrame最好的类比是Excel里的一张工作表有行、有列、有表头每个单元格都能填不同类型的内容。但DataFrame比Excel更严格——同一列只允许一种数据类型行和列都有对应的标签index和columns而这种强约束恰恰是它能高效做筛选、聚合、关联的前提。所以创建DataFrame的核心不是机械地把数据塞进某种结构而是必须回答三个问题数据从哪里来是手写构造、程序生成、文件读取还是数据库查询行与列如何对齐每列叫什么名字每行用什么索引数据与标签如何一一对应每个字段的类型是什么是字符、整数、浮点、日期还是类别。这三个问题想清楚了代码怎么写都是顺理成章想不清楚后面必然要花大量时间在数据类型转换、缺失值清理上。我见过不少同事一边写一边改代码看起来像在追着报错跑。经验是创建DataFrame时多花三十秒想清楚结构和类型比事后用十行astype救场划算得多。尤其是创建时日期列是字符串、金额列是object这种问题前期定好类型后面可以直接省掉一整段清洗代码。pandas里有一句流传很久的话——DataFrame创建决定了数据分析的下限这句话虽然略带夸张但方向是对的。1.2 几种创建方式的选型逻辑pandas创建DataFrame的常见来源大致分五类从字典创建、从列表或二维数组创建、从NumPy数组创建、从外部文件读取、从数据库查询。先看一张对照表再逐个解释为什么选它创建方式典型代码适合场景注意点字典创建pd.DataFrame({a: [1,2], b: [3,4]})字段明确、数据量小、手工构造字典键就是列名列顺序由传入顺序决定列表创建pd.DataFrame([(1,2),(3,4)], columns[a,b])元组或列表组成的行数据必须显式给columns否则列名是0、1、2NumPy数组创建pd.DataFrame(arr, columns[a,b], index...)矩阵计算、机器学习特征维度、列名、列数必须严格匹配外部文件读取pd.read_csv(data.csv)真实项目中最常用返回对象本身就是DataFrame要处理编码与类型数据库查询pd.read_sql(select * from t, conn)数据在数据库里需要SQLAlchemy或DBAPI连接对象选型逻辑其实很简单数据在内存里就选前三种数据在磁盘或数据库就选后两种。但有一个原则我反复强调——不到万不得已不要在循环里逐行向DataFrame追加数据。原因是DataFrame的内存结构是按块存储的每append一次就要重新分配并复制一次数据几百行看不出来几万行就开始明显卡顿。正确做法是先把所有行收集到普通列表最后一次性交给pd.DataFrame()或者用pd.concat批量合并。这个习惯如果从第一天就养成后面处理大文件时会轻松很多。2. 核心细节解析与实操要点2.1 从字典创建DataFrame两种写法场景完全不同最常见的字典创建写法是字典的值是一列数据import pandas as pd df pd.DataFrame({ name: [张三, 李四, 王五], age: [23, 31, 28], city: [北京, 上海, 广州] }) print(df)输出如下name age city 0 张三 23 北京 1 李四 31 上海 2 王五 28 广州这里的逻辑是字典的键会成为列名每个值是一个列表代表这一列的所有数据。pandas会自动为每行分配0、1、2这样的RangeIndex不需要你手动去数行数。这种纵向列传值的写法最贴近人脑对表格的认知——先有列名再逐列填内容很适合手工构造小型测试集。另一种写法是每行一个字典把每个字典看作一条记录df pd.DataFrame([ {name: 张三, age: 23, city: 北京}, {name: 李四, age: 31, city: 上海}, {name: 王五, age: 28, city: 广州}, ])这种方式在实际项目中反而更常用因为从爬虫接口拿回来的JSON数据天然就是list[dict]结构每条记录一个字典直接传给pd.DataFrame()即可完成转换。反过来如果你手里是一张从Excel复制出来的二维表则更适合用dict of list组织数据。两种写法没有优劣之分只看数据源长什么样。创建时还可以显式指定columns和index。columns参数一方面控制列的顺序另一方面也能起到筛选列的作用——如果数据字典里没有对应列pandas会自动补NaNindex参数则可以为行指定索引常用于时间序列数据比如pd.DataFrame(data, indexpd.date_range(2024-01-01, periods3))。我自己的习惯是只要数据是有顺序含义的就第一时间把index做好而不是等后面再set_index否则中间步骤容易因为索引错位导致莫名其妙的结果。提示用字典创建时所有字典值的长度必须一致否则pandas会直接报错ValueError: All arrays must be of the same length。这个错误本质上就是你的表格缺了一列没填完检查一下数据源哪条记录不完整即可。2.2 从列表或二维数组创建DataFrame当数据本身就是二维结构时用列表或NumPy二维数组来创建最直接import numpy as np import pandas as pd # 二维列表每行是一条记录 data_rows [ [2024-01-01, A001, 399.00], [2024-01-01, A002, 159.00], [2024-01-02, A003, 219.50], ] df pd.DataFrame(data_rows, columns[date, order_id, amount]) print(df) # NumPy二维数组矩阵计算结果直接转表 arr np.random.randn(100, 4) df_arr pd.DataFrame(arr, columns[f1, f2, f3, f4]) print(df_arr.head())df_arr这个例子里np.random.randn(100, 4)生成一个100行4列的随机数矩阵pd.DataFrame直接把它包装成带列名的表格。索引仍然是默认的0到99列名则由columns参数指定。这种方式的优点是原生态——从CSV读进来、从矩阵计算拿到结果、从旧系统导出数据天然就是二维结构缺点是列名语义完全靠代码维护一不留神就会列错误位。用二维数组创建时有个最常见的坑数组的shape和columns数量不一致。np.random.randn(100, 4)有4列你如果只传3个列名pandas不会自动帮你截断而是直接抛ValueError。排查方法很简单先打印arr.shape看几个维度再数一遍columns列表长度两边对齐再创建。另一个细节是用pd.DataFrame(rows)时如果不指定columns列名会变成0、1、2这样的数字这在真实项目中几乎没有任何语义价值所以千万别偷懒列名一定要给。2.3 创建时就把类型定好省掉后面一堆astype创建DataFrame时的高频问题是data里全是字符串后面要算均值、排序结果一运行就报错。这里要养成一个习惯——创建阶段能定类型就别拖到使用阶段。手动创建时可以用dtype参数指定默认类型但注意pd.DataFrame构造器本身只支持一个全局dtype并不能按列分别指定这是很多教程容易误导的地方所以更稳妥的方式是创建后立刻用astype逐列转换df pd.DataFrame({ date: [2024-01-01, 2024-01-02], order_id: [A001, A002], amount: [399.00, 159.00] }) # 立刻做类型校正 df[amount] df[amount].astype(float) df[date] pd.to_datetime(df[date]) df[order_id] df[order_id].astype(string) print(df.dtypes)输出date datetime64[ns] order_id string amount float64 dtype: object读文件时在源头转换效率更高也是最推荐的做法df pd.read_csv( orders.csv, parse_dates[date], # 日期字段自动解析为datetime64 dtype{order_id: string, amount: float64} )parse_dates参数会把指定列自动尝试解析成时间类型省去手动to_datetimedtype参数则强制指定字段类型。这里尤其要提防的是订单编号这类字段——如果不在读取时指定dtype{order_id: string}pandas极有可能把001读成整数1导致编号丢失前导零。类似的问题在账号、电话号码列上也特别常见别等分析结果不对劲了才回头查原始数据。至于字符串转数值、字符串转日期这两个操作标准套路是把errorscoerce写进去df[amount] pd.to_numeric(df[amount], errorscoerce) df[date] pd.to_datetime(df[date], errorscoerce)errorscoerce的意思是遇到无法解析的值不抛异常而是转成NaN保留下来。这样做的价值在于你可以在后续步骤统一查看哪些值有问题而不是被一个脏数据打断整条流程。不过要记住被coerce成NaN的值本身就是脏数据后续一定要单独处理否则它会悄悄影响平均值和汇总结果。2.4 文件读取真实项目中最常用的创建方式真实项目里DataFrame通常不是手敲出来的而是读进来的。pd.read_csv是数据侧最核心的入口理解它的常用参数比多背几种构造方法更有价值df pd.read_csv(sales.csv, encodingutf-8-sig)第一个参数是文件路径实际使用中我会顺手加三个常用参数encodingutf-8-sig兼容Excel导出的带BOM的CSV避免中文乱码sep默认分隔符是逗号遇到分号或制表符就传sep;或sep\theader默认0表示第一行是列名如果文件没有表头传headerNone并手动指定names参数。还有两个我几乎每次都会用的参数usecols只读取需要的列避免大文件占满内存nrows先读前几千行做数据侦查确认格式无误后再全量加载。除了CSV另外两个高频入口是read_excel和read_sqldf_excel pd.read_excel(data.xlsx, sheet_name订单, header0) df_sql pd.read_sql(SELECT id, name, amount FROM orders, conn)read_excel需要安装openpyxl或xlrd库sheet_name可以直接传工作表名称read_sql需要SQLAlchemy或DBAPI连接对象返回的同样是DataFrame。所以理解创建DataFrame不能只盯着pd.DataFrame构造函数读写文件、读写数据库本质上都是在创建DataFrame而且往往是更常见的方式。顺便提一句环境配置很多人在pycharm里新建项目后装pandas总是超时换用清华PyPI镜像站加速安装通常能立刻解决。安装命令大致是pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple这是国内正常的软件源加速方式日常开发中非常实用。3. 实操过程与核心环节实现一个订单数据的完整例子3.1 场景设定先造一批数据实战环节我们模拟一个电商订单场景。目标是把一批零散的订单明细整理成DataFrame并完成初步的类型校正与清洗。第一步永远是从无到有造一批测试数据毕竟真实数据涉及隐私而且造数据的过程本身就能帮你理解数据长什么样才算合理。import numpy as np import pandas as pd np.random.seed(42) n 1000 # 生成等间隔时间戳模拟订单发生时间 dates pd.date_range(2024-01-01, periodsn, freqh) # 生成订单编号、金额和区域顺便塞20个缺失金额模拟脏数据 order_ids [fOD{10000i} for i in range(n)] amounts np.round(np.random.uniform(50, 5000, n), 2) regions np.random.choice([华东, 华北, 华南, 西南], n) amounts[np.random.choice(np.arange(n), 20, replaceFalse)] np.nan sales_df pd.DataFrame({ order_date: dates, order_id: order_ids, amount: amounts, region: regions }) print(sales_df.head()) print(sales_df.info())这里有几个细节值得展开。pd.date_range(2024-01-01, periodsn, freqh)生成的是从2024年1月1日0点开始、每小时一条的等间隔时间序列目的是模拟真实订单时间戳np.random.uniform(50, 5000, n)生成连续金额后四舍五入到两位小数符合钱只保留分位的业务习惯故意往amount列塞20个NaN是为了让后续清洗环节有东西可操作。np.random.seed(42)固定随机种子保证每次跑出来的数据完全一致——这在写演示代码和测试时特别重要数据每次不同会让你怀疑是自己代码写错了还是随机性导致的差异。从创建的角度看这段代码用的就是字典创建和预生成NumPy数组的组合拳同时提前把order_date列做成了datetime64[ns]类型金额列也成了float64。这正是第2节反复提到的思路创建时尽量把类型定好后面才不需要疯狂astype。3.2 从创建走向清洗把表变成干净可用的样子DataFrame创建完成后别急着做统计分析第一步用df.info()做一次体检print(sales_df.info())正常情况下你会看到类似下面的信息class pandas.core.frame.DataFrame RangeIndex: 1000 entries, 0 to 999 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 order_date 1000 non-null datetime64[ns] 1 order_id 1000 non-null object 2 amount 980 non-null float64 3 region 1000 non-null object信息一目了然1000行、4列amount列只有980个非空值说明有20个NaN。接下来做三项常规清洗处理缺失值、修正类型、对分类字段做优化存储。对缺失金额最保守的做法是dropna(subset[amount])删掉缺失行如果业务上允许填充也可以用fillna配合分组均值填充。先看数量再决定方案——缺失比例在5%以内且没有明显规律删掉通常不影响大局如果缺失集中在某一天或某个区域那就要排查业务原因了。类型修正方面假设字段是从外部文件读进来的字符串标准套路就是对金额执行pd.to_numeric(..., errorscoerce)对日期执行pd.to_datetime(..., errorscoerce)。sales_df_clean sales_df.dropna(subset[amount]) sales_df_clean[region] sales_df_clean[region].astype(category) # 如果是从文件读进来的字符串补上这两行 # sales_df_clean[amount] pd.to_numeric(sales_df_clean[amount], errorscoerce) # sales_df_clean[order_date] pd.to_datetime(sales_df_clean[order_date]) print(sales_df_clean.dtypes)把区域region转成category类型是一个容易被忽视的优化点当某个列只有少数几个取值object类型会占用更多内存而category类型会把重复值映射成整数编号在几百万行数据上能省下可观的内存分组聚合时也会更快。处理完类型再检查一下索引是否连续sales_df_clean sales_df_clean.reset_index(dropTrue)reset_index(dropTrue)会把删除行之后断裂的索引重新编号这样后续按位置切片、合并时不会出现莫名其妙的索引空洞。这一步看起来小但在多人协作的项目里索引不连续常常是为什么我的结果少了4行的罪魁祸首。3.3 结果校验与导出清洗完成后最后一步是校验和导出。很多初学者洗完数据直接print看一下觉得对就交差了但真实项目里我更推荐用断言把核心约束写进脚本# 核心校验类型、行数、无缺失 assert sales_df_clean[amount].dtype np.float64 assert len(sales_df_clean) 980 assert sales_df_clean[amount].notna().all() # 导出为CSV sales_df_clean.to_csv(sales_clean.csv, indexFalse, encodingutf-8-sig)导出的两个参数值得解释indexFalse表示不写索引列否则下次读回来时会多出一列莫名其妙的Unnamed: 0encodingutf-8-sig则是为了兼容Excel——加了BOM头之后用Excel直接打开中文CSV不会乱码。这两个参数几乎每次导出都会用到属于固定记忆项。到这里一个完整的创建DataFrame → 体检 → 清洗 → 校验 → 导出链路就通顺了。对刚上手的同学建议把这段代码在自己的环境里逐行敲一遍重点观察df.info()输出的Dtype列在清洗前后发生了什么变化——类型对了后面统计和绘图才稳得住否则画图画到一半发现X轴全是字符串乱序那种体验真的很磨人。4. 常见问题与排查技巧实录4.1 高频问题速查表根据我在实际项目中反复遇到的报错我把最典型的几个问题、现象、原因和解决方案整理成速查表建议截图存一份问题现象常见原因解决方案KeyError: 列名df[amount]找不到列列名含空格或大小写不一致CSV表头被当成第一行数据打印df.columns确认真实列名CSV用header0或headerNonenamesValueError: All arrays must be of the same length字典创建时列长度不一致某个键对应的列表比其他短检查数据源补全缺失记录或删除不完整行dtype是object数值列sum()报错文件里混入逗号、百分号、空字符串pd.to_numeric(..., errorscoerce)日期筛选失效按月份筛选报错或结果为空日期列被读成字符串read_csv加parse_dates或pd.to_datetime中文乱码读CSV中文乱码文件编码不是utf-8或带BOMencodingutf-8-sig或gbkdf.append不存在AttributeErrorpandas 2.0已移除append方法用pd.concat替代SettingWithCopyWarning对切片后的df赋值时报警告链式赋值如df[df.a0][b]1用.loc或先copy()再操作4.2 三个最典型的坑重点排雷坑一列名和数据隐形错位。很多Excel导出的CSV第0行并不是真正的表头而是一条标题或空行。如果不指定header和skiprows列名就会变成订单明细表这种人类标题真实表头反而成了数据区第一行后续访问字段会全部错乱。我的习惯是拿到任何文件都不先写业务代码而是先打印df.head(5)和df.columns.tolist()花十秒钟确认表头长什么样再决定要不要加skiprows。坑二把文本型数字直接强转。金额带千分位3,900.00读进来就是字符串新手直接df[amount].astype(float)会当场炸掉因为float不认识逗号。正确顺序是先pd.to_numeric(df[amount], errorscoerce)软转换把非法值变成NaN再观察哪些记录有问题最后统一填充或删除。这个先软转、再找脏值、最后处理的顺序不能反——先coerce再查NaN绝大多数文本型数字问题都能解决。坑三列明明存在却提示KeyError。这种情况常见于列名带有空格、中文括号、大小写不统一比如Excel自动把列名命名为order date而不是order_date。你写df[order_date]时自然找不到。排查方法极度简单打印df.columns把每一列名字原样看清楚然后复制粘贴到代码里不要凭记忆手敲。还有一个变种情况是用df.列名这种属性访问方式——只要列名里有空格或特殊字符就不行而且列名和已有的方法同名也不行老老实实用df[列名]。4.3 一条实用经验创建之前先侦查最后分享一个我自己踩过多次坑之后养成的习惯。拿到任何数据源我不会直接写pd.DataFrame或pd.read_csv而是先做一次最小规模的侦查如果是文件用Python内置的open读前3行看看分隔符和表头长什么样如果是接口返回先print响应中第一条记录的字典结构如果是数据库先执行SELECT * FROM 表 LIMIT 5观察字段名和值类型。侦查完再确定创建方案和dtype策略。这不是浪费时间而是用两分钟避免后面两小时的返工。创建DataFrame的能力并不在于能背出多少种构造方法而在于面对真实、杂乱的数据时能快速判断它应该以什么结构、什么类型进入pandas。这个判断力靠的是日常积累和主动排坑不是看几篇教程就能获得的。我再多说一句日常感触每次看到刚入门的同学在论坛里问为什么我的DataFrame做不了groupby为什么日期排序全乱了十有八九都是创建阶段就把类型搞成了object、把日期搞成了字符串。这篇文章我没有展开讲透视、合并这些高阶操作只围绕创建这一个动作反复讲——把结构、类型、来源想明白后面真的可以少掉一半的debug时间。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号