PythonPandas数据处理入门指南
时间:2025-08-31 23:32:50 277浏览 收藏
想入门Python数据分析?这篇Pandas教程为你量身定制!Pandas作为Python数据科学的基石,提供了高效的数据结构和分析工具,如同数据分析领域的瑞士军刀。本教程将带你快速掌握Pandas的核心用法,从安装导入开始,深入讲解DataFrame和Series的创建、数据读取与初步探索(如head(), tail(), info(), describe()等)。你将学会如何进行数据选择与过滤(loc和iloc的使用),以及关键的数据清洗技巧,包括缺失值处理(dropna(), fillna())、重复值处理(drop_duplicates())、异常值检测与处理(IQR),文本数据清洗(str方法)和日期时间数据处理(to_datetime())。此外,还将介绍数据聚合与分组分析(groupby()),以及数据合并与连接(pd.merge(), pd.concat())。本文还总结了实际项目中的常见陷阱和最佳实践,助你避免链式赋值警告、性能问题和内存占用等问题,让你的数据分析之路更加顺畅。
Pandas数据清洗常用技巧包括处理缺失值、重复值、异常值、文本数据、日期时间及数据标准化。具体为:用dropna()或fillna()处理缺失值;drop_duplicates()去除重复数据;通过IQR或标准差识别异常值并合理处理;利用str方法清洗文本,如去空格、大小写转换;用to_datetime统一日期格式;结合业务需求进行数据归一化。同时需注意链式赋值警告、性能优化和内存管理等最佳实践。
Pandas是Python数据科学领域的一把瑞士军刀,它提供了一系列高效的数据结构和数据分析工具,让你能轻松处理和分析表格型数据,就像在用一个超级强大的Excel。无论是数据清洗、转换、聚合还是探索性分析,Pandas都能提供直观且高性能的解决方案。
解决方案
要开始使用Pandas,第一步通常是导入它,约定俗成地使用pd
作为别名。
import pandas as pd import numpy as np # 经常和Pandas一起使用
1. 创建数据结构:DataFrame和Series
Pandas最核心的两个数据结构是DataFrame和Series。Series可以看作带标签的一维数组,而DataFrame则是一个二维的、表格型数据结构,每列可以有不同的数据类型。
创建Series:
s = pd.Series([1, 3, 5, np.nan, 6, 8]) print(s) # 输出: # 0 1.0 # 1 3.0 # 2 5.0 # 3 NaN # 4 6.0 # 5 8.0 # dtype: float64
创建DataFrame,这通常是我们日常工作中打交道最多的。可以从字典、列表的列表,或者直接从CSV、Excel文件加载。
# 从字典创建DataFrame data = { '姓名': ['张三', '李四', '王五', '赵六'], '年龄': [25, 30, 28, 35], '城市': ['北京', '上海', '广州', '深圳'], '薪资': [8000, 12000, 9000, 15000] } df = pd.DataFrame(data) print(df) # 输出: # 姓名 年龄 城市 薪资 # 0 张三 25 北京 8000 # 1 李四 30 上海 12000 # 2 王五 28 广州 9000 # 3 赵六 35 深圳 15000
2. 从文件加载数据
真实世界的数据很少是手动输入的,更多是从文件读取。Pandas对多种文件格式提供了强大的支持。
# 读取CSV文件 # df_csv = pd.read_csv('your_data.csv') # 读取Excel文件 # df_excel = pd.read_excel('your_data.xlsx', sheet_name='Sheet1') # 读取JSON文件 # df_json = pd.read_json('your_data.json')
通常,pd.read_csv()
是最常用的函数,因为它能处理各种分隔符、编码问题。
3. 数据查看与初步探索
拿到数据后,第一件事是看看它长什么样。
print(df.head()) # 查看前5行 print(df.tail(3)) # 查看后3行 print(df.info()) # 查看数据概览,包括列名、非空值数量、数据类型 print(df.describe()) # 对数值列进行统计描述,如均值、标准差、最大最小值等 print(df.shape) # 查看行数和列数 (rows, columns) print(df.columns) # 查看所有列名
4. 数据选择与过滤
这是数据分析的基础操作,如何精准地取出你想要的数据。
选择单列或多列:
print(df['姓名']) # 选择单列,返回Series print(df[['姓名', '薪资']]) # 选择多列,返回DataFrame
使用loc
和iloc
进行行和列的选择:
loc
:基于标签(列名、行索引)选择。iloc
:基于整数位置选择。
print(df.loc[0]) # 选择第一行 print(df.loc[0, '姓名']) # 选择第一行'姓名'列的值 print(df.loc[0:2, ['姓名', '年龄']]) # 选择0到2行(包含2),'姓名'和'年龄'列 print(df.iloc[0:3, 0:2]) # 选择前3行,前2列(基于位置)
条件过滤:
# 筛选年龄大于30的员工 older_employees = df[df['年龄'] > 30] print(older_employees) # 筛选城市是上海且薪资高于10000的员工 filtered_df = df[(df['城市'] == '上海') & (df['薪资'] > 10000)] print(filtered_df)
5. 数据清洗与处理
这是数据分析中最耗时也最关键的一步。
缺失值处理:
# 检查缺失值 print(df.isnull().sum()) # 删除含有缺失值的行 # df_cleaned = df.dropna() # 填充缺失值 # df_filled = df.fillna(value=0) # 用0填充所有缺失值 # df['年龄'].fillna(df['年龄'].mean(), inplace=True) # 用年龄均值填充年龄列的缺失值
数据类型转换:
# 将某一列转换为特定类型 # df['年龄'] = df['年龄'].astype(int)
重复值处理:
# 检查重复行 # print(df.duplicated().sum()) # 删除重复行 # df_no_duplicates = df.drop_duplicates()
6. 数据聚合与分组
groupby()
是Pandas中最强大的功能之一,它允许你按照一个或多个列对数据进行分组,然后对每个组执行聚合操作(如求和、均值、计数等)。
# 按照城市分组,计算每个城市的平均薪资 avg_salary_by_city = df.groupby('城市')['薪资'].mean() print(avg_salary_by_city) # 按照城市和年龄分组,计算每个组的薪资总和 grouped_data = df.groupby(['城市', '年龄'])['薪资'].sum() print(grouped_data) # 可以同时应用多个聚合函数 agg_data = df.groupby('城市')['薪资'].agg(['mean', 'max', 'min', 'count']) print(agg_data)
7. 数据合并与连接
当数据分散在多个DataFrame中时,你需要将它们合并起来。
df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': np.random.randn(4)}) df2 = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value2': np.random.randn(4)}) # 内连接:只保留两个DataFrame中key都存在的行 merged_df = pd.merge(df1, df2, on='key', how='inner') print(merged_df) # 左连接:保留左边DataFrame的所有行,匹配右边DataFrame的行 left_merged_df = pd.merge(df1, df2, on='key', how='left') print(left_merged_df) # 拼接(Stacking):将多个DataFrame按行或列堆叠起来 df3 = pd.DataFrame({'key': ['G', 'H'], 'value': np.random.randn(2)}) concatenated_df = pd.concat([df1, df3], ignore_index=True) print(concatenated_df)
Pandas数据清洗的常用技巧有哪些?
数据清洗,这活儿说起来简单,做起来往往是整个项目最磨人的部分。我的经验是,没有哪个数据集是“干净”的,总有些奇奇怪怪的脏数据等着你去处理。Pandas在这方面提供了很多趁手的工具。
除了前面提到的缺失值、重复值处理,还有几个点我觉得特别重要:
异常值检测与处理: 异常值可能是数据录入错误,也可能代表了真实的特殊情况。识别它们是第一步。常用的方法有基于统计(如3倍标准差、IQR范围)或可视化(箱线图、散点图)。Pandas本身没有直接的异常值检测函数,但你可以结合其统计功能轻松实现。
# 假设我们想找出薪资的异常值 Q1 = df['薪资'].quantile(0.25) Q3 = df['薪资'].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR outliers = df[(df['薪资'] < lower_bound) | (df['薪资'] > upper_bound)] print("薪资异常值:\n", outliers) # 处理方式可以是删除、替换为均值/中位数,或者上限/下限值 # df['薪资'] = np.where(df['薪资'] > upper_bound, upper_bound, df['薪资'])
处理异常值需要谨慎,有时它们是宝贵的信息,比如高价值客户或系统故障。
文本数据清洗: 字符串列往往是最混乱的。大小写不一致、多余空格、特殊字符、错别字……这些都得处理。Pandas的
str
访问器非常强大。df['城市'] = df['城市'].str.strip() # 移除前后空格 df['城市'] = df['城市'].str.lower() # 转换为小写 df['姓名'] = df['姓名'].str.replace('张', 'ZHANG') # 替换字符 # 使用正则表达式进行更复杂的匹配和替换 # df['描述'] = df['描述'].str.replace(r'[^\w\s]', '', regex=True) # 移除所有非字母数字和空格的字符
这里面有个小坑,如果你的字符串列里有
NaN
,直接调用str
方法会报错,需要先填充或过滤掉缺失值。日期时间数据处理: 日期时间格式不统一是常态。Pandas的
to_datetime
函数能智能地解析多种日期时间格式。# df['日期'] = pd.to_datetime(df['日期'], errors='coerce') # errors='coerce'会将无法解析的日期转换为NaT(Not a Time) # 提取年份、月份、星期几等 # df['年份'] = df['日期'].dt.year # df['月份'] = df['日期'].dt.month
处理日期时间时,时区问题也常常让人头疼,特别是在处理跨国数据时。Pandas提供了
tz_localize
和tz_convert
来处理这些。数据标准化/归一化: 在进行机器学习前,往往需要将不同量纲的数值特征进行缩放。虽然这通常在Pandas之外(如scikit-learn)完成,但Pandas是数据准备的平台。
# 简单的Min-Max标准化示例 # df['薪资_normalized'] = (df['薪资'] - df['薪资'].min()) / (df['薪资'].max() - df['薪资'].min())
这些技巧,用得多了自然熟练,但每次遇到新数据,我还是会先花大量时间在清洗上,毕竟“垃圾进,垃圾出”是数据分析的铁律。
Pandas如何进行数据聚合和分组分析?
数据聚合和分组分析是Pandas的灵魂所在,它允许我们从宏观角度理解数据,而不是纠结于每一行。groupby()
方法就是实现这一点的核心。
想象一下,你有一堆销售数据,你可能想知道每个产品类别的总销售额,或者每个地区的平均订单价值。这就是groupby()
的用武之地。
基本流程是:Split-Apply-Combine。
- Split(拆分):根据一个或多个键(列)将DataFrame拆分成若干个组。
- Apply(应用):对每个组独立地应用一个函数(聚合、转换或过滤)。
- Combine(组合):将所有组的结果组合成一个新的DataFrame或Series。
最常见的应用是聚合函数:
# 假设我们有一个更复杂的销售数据 sales_data = { '产品类别': ['电子', '服装', '电子', '食品', '服装', '电子', '食品'], '地区': ['华东', '华南', '华东', '华北', '华南', '华东', '华北'], '销售额': [1200, 500, 1500, 300, 800, 1000, 450], '订单数量': [10, 5, 12, 3, 8, 9, 4] } sales_df = pd.DataFrame(sales_data) print("原始销售数据:\n", sales_df) # 按产品类别计算总销售额 total_sales_by_category = sales_df.groupby('产品类别')['销售额'].sum() print("\n按产品类别总销售额:\n", total_sales_by_category) # 按地区计算平均订单数量 avg_orders_by_region = sales_df.groupby('地区')['订单数量'].mean() print("\n按地区平均订单数量:\n", avg_orders_by_region)
更进一步,你可以同时对多个列应用不同的聚合函数,使用agg()
方法:
# 按产品类别和地区分组,同时计算销售额的总和、平均值和订单数量的总和 multi_agg = sales_df.groupby(['产品类别', '地区']).agg( 总销售额=('销售额', 'sum'), 平均销售额=('销售额', 'mean'), 总订单数量=('订单数量', 'sum') ) print("\n多重聚合结果:\n", multi_agg)
这里我用了Python 3.6+的f-string风格的agg
语法,它让输出的列名更清晰,我个人觉得比传入字典的旧方式更直观。
除了聚合,groupby()
还可以用于转换(transform)和过滤(filter)。
- transform:对每个组应用一个函数,但返回的结果与原始DataFrame的索引对齐,常用于填充组内缺失值或进行组内标准化。
# 计算每个产品类别销售额占该类别总销售额的比例 sales_df['类别销售额占比'] = sales_df.groupby('产品类别')['销售额'].transform(lambda x: x / x.sum()) print("\n带类别销售额占比的数据:\n", sales_df)
- filter:根据组的某些特性来筛选组。
# 筛选出总销售额超过2000的产品类别 filtered_categories = sales_df.groupby('产品类别').filter(lambda x: x['销售额'].sum() > 2000) print("\n总销售额超过2000的产品类别数据:\n", filtered_categories)
这些高级用法让
groupby()
变得极其灵活,能解决很多复杂的数据分析问题。我发现很多人刚开始用Pandas时,经常会尝试用循环来解决分组问题,但一旦掌握了groupby()
,效率会提升好几个数量级。
Pandas在实际项目中常见的陷阱与最佳实践?
在实际项目中使用Pandas,我遇到过不少坑,也总结了一些经验。它确实强大,但用不好也容易“翻车”。
常见陷阱:
链式赋值警告(SettingWithCopyWarning): 这是新手最常遇到的问题之一。当你对一个DataFrame的“视图”进行修改时,Pandas会发出警告。
# 错误示例:可能引发SettingWithCopyWarning # df_subset = df[df['年龄'] > 30] # df_subset['薪资'] = df_subset['薪资'] * 1.1 # 这里的修改可能不会反映到原始df,也可能报错
最佳实践: 明确地使用
.loc
或.copy()
。如果你想创建一个独立的DataFrame副本,就用.copy()
;如果想在原始DataFrame上修改,且操作是基于条件选择的,就用.loc
。df_subset = df[df['年龄'] > 30].copy() # 明确复制一份 df_subset['薪资'] = df_subset['薪资'] * 1.1 # 在原始DataFrame上修改,使用.loc df.loc[df['年龄'] > 30, '薪资'] = df.loc[df['年龄'] > 30, '薪资'] * 1.1
这个坑我踩过好几次,导致数据修改没生效,或者莫名其妙的错误。
性能问题: 对大型数据集使用循环(
for
循环、apply
配合lambda函数)往往效率低下。# 性能差的示例:逐行处理 # for index, row in df.iterrows(): # df.loc[index, '新列'] = row['列A'] + row['列B']
最佳实践: 尽可能使用Pandas的向量化操作。Pandas底层是C语言实现的,向量化操作能充分利用CPU的并行计算能力。
df['新列'] = df['列A'] + df['列B'] # 向量化操作
如果必须使用
apply
,尽量用在Series上,或者确保你的函数是高度优化的。对于非常复杂的操作,考虑使用df.apply(..., axis=1)
,但要清楚这通常比向量化慢。更极致的性能需求,可以考虑numba
或modin
。内存占用: 大数据集可能导致内存不足。特别是字符串和日期时间列,它们在Pandas中可能比你想象的更占用内存。 最佳实践:
- 选择合适的数据类型: 对于整数或浮点数,使用
int8
,int16
,float32
等更小的类型。df.info(memory_usage='deep')
可以查看详细内存占用。 - Categorical类型: 对于重复值较多的字符串列(如国家、城市),转换为
category
类型可以显著节省内存。df['城市'] = df['城市'].astype('category')
- 分块读取: 对于超大型文件,使用
pd.read_csv(..., chunksize=...)
分块读取和处理数据。
- 选择合适的数据类型: 对于整数或浮点数,使用
索引管理不当: 索引是Pandas的强大之处,但如果处理不当,也可能导致问题,比如合并时索引不匹配。 最佳实践:
- 在合并或拼接DataFrame时,明确指定
on
参数,或者在不需要索引时使用reset_index()
。 - 如果索引有实际意义(如时间序列),充分利用它进行时间序列操作。
- 在合并或拼接DataFrame时,明确指定
这些陷阱,说到底都是对Pandas底层机制理解不够深入造成的。多实践,多看官方文档,你会发现Pandas的设计哲学非常精妙。它不是一个简单的工具库,而是一个强大的数据处理框架,值得我们花时间去深入学习。
好了,本文到此结束,带大家了解了《PythonPandas数据处理入门指南》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
118 收藏
-
330 收藏
-
357 收藏
-
107 收藏
-
208 收藏
-
155 收藏
-
123 收藏
-
402 收藏
-
469 收藏
-
476 收藏
-
281 收藏
-
169 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 499次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习