引言
在现代办公环境中,excel无疑是最常用的数据管理工具之一。然而,当数据量庞大、操作重复性高时,手动处理excel表格不仅效率低下,还极易出错。这时,python的强大功能就显得尤为重要,特别是其数据分析利器——pandas库。
pandas提供了一套高性能、易于使用的数据结构和数据分析工具,能够让你以编程的方式高效地读取、处理、分析乃至写入excel文件。对于希望提升办公效率、摆脱繁琐重复工作的你来说,学习如何使用pandas操作excel,无疑是一项极具价值的技能。
本篇博客将作为你的pandas操作excel入门指南,从最基础的数据读取开始,逐步深入到数据的查看、选择、清洗、排序、筛选、应用函数,最终实现将处理后的数据写入新的excel文件。无论你是完全的编程新手,还是对python自动化办公充满好奇,都将通过本文获得扎实的实践基础。
让我们一起踏上这段高效办公的自动化之旅吧!
前置准备
在开始之前,请确保你的计算机上已经安装了python环境,并且安装了本教程所需的关键库。
1. 安装python
如果你尚未安装python,推荐访问python官方网站下载并安装最新版本。安装时请务必勾选“add python to path”选项。
2. 安装pandas和excel读写库
pandas本身不直接支持excel文件的读写,它依赖于其他库来完成这项工作。对于.xlsx格式的excel文件(新版excel),我们需要安装openpyxl;对于.xls格式的excel文件(旧版excel),则需要xlrd。通常,我们都会安装openpyxl。
打开你的命令行工具(windows用户是cmd或powershell,macos/linux用户是terminal),运行以下命令进行安装:
pip install pandas openpyxl
安装成功后,你就可以开始使用pandas了。
实战演练:pandas操作excel的八大核心技能
为了更好地演示pandas的功能,我们首先需要一个示例excel文件。
准备工作:创建示例excel文件
请在你的工作目录下创建一个名为员工信息.xlsx的excel文件,并填入以下内容:
员工信息.xlsx
| 员工id | 姓名 | 部门 | 职位 | 入职日期 | 工资 | 绩效等级 |
|---|---|---|---|---|---|---|
| 1001 | 张三 | 销售部 | 销售经理 | 2020-01-01 | 8000 | a |
| 1002 | 李四 | 市场部 | 市场专员 | 2021-03-15 | 6500 | b |
| 1003 | 王五 | 销售部 | 销售代表 | 2022-07-20 | 5000 | c |
| 1004 | 赵六 | 研发部 | 软件工程师 | 2019-11-01 | 12000 | a |
| 1005 | 孙七 | 市场部 | 市场经理 | 2018-05-10 | 9000 | a |
| 1006 | 周八 | 销售部 | 销售代表 | 2023-01-01 | 5200 | b |
| 1007 | 吴九 | 研发部 | 高级工程师 | 2017-09-01 | 15000 | a |
| 1008 | 郑十 | 市场部 | 市场专员 | 2023-02-01 | 6000 | c |
| 1009 | 陈十一 | 销售部 | nan | 2022-04-01 | 5500 | b |
| 1010 | 钱十二 | 研发部 | 软件工程师 | 2021-08-01 | 11000 | nan |
其中,nan表示缺失值。
现在,我们可以开始用python和pandas操作这个文件了。
import pandas as pd # 定义excel文件路径 file_path = '员工信息.xlsx'
1. 读取excel文件
读取excel文件是所有操作的第一步。pandas提供了read_excel()函数来轻松完成这项任务。
# 读取整个excel文件的第一个工作表
df = pd.read_excel(file_path)
print("------ 原始数据框 ------")
print(df)
# 读取指定工作表 (如果excel文件有多个工作表,例如:sheet_name='sheet2')
# df_sheet2 = pd.read_excel(file_path, sheet_name='sheet2')
# print("\n------ sheet2 数据框 ------")
# print(df_sheet2)
# 读取时指定某一列作为索引 (例如:员工id作为索引)
# df_indexed = pd.read_excel(file_path, index_col='员工id')
# print("\n------ 以员工id为索引的数据框 ------")
# print(df_indexed)
解释:
pd.read_excel(file_path):这是最基本的用法,它会读取excel文件中的第一个工作表。sheet_name参数:用于指定要读取的工作表的名称或索引(从0开始)。如果不指定,默认为第一个工作表。index_col参数:可以指定excel文件中的某一列作为dataframe的索引。
2. 查看数据
读取数据后,我们需要快速了解数据的概况,包括其结构、内容、数据类型等。
print("\n------ 查看数据概况 ------")
# 查看前5行数据 (默认值)
print("\n前5行数据:")
print(df.head())
# 查看后3行数据
print("\n后3行数据:")
print(df.tail(3))
# 查看数据框的维度 (行数, 列数)
print("\n数据框维度 (行数, 列数):", df.shape)
# 查看所有列名
print("\n所有列名:", df.columns.tolist())
# 查看数据框的简要信息,包括列名、非空值数量、数据类型和内存占用
print("\n数据框信息:")
df.info()
# 查看数值列的描述性统计信息 (计数、均值、标准差、最小值、25/50/75分位数、最大值)
print("\n数值列描述性统计:")
print(df.describe())
# 查看所有列的描述性统计信息 (包括非数值列)
print("\n所有列描述性统计:")
print(df.describe(include='all'))
解释:
.head(n)/.tail(n):快速预览数据的前n行或后n行,默认n=5。.shape:返回一个元组,表示dataframe的行数和列数。.columns:返回所有列的名称。.info():提供数据的摘要信息,包括每列的名称、非空值的数量、数据类型以及内存使用情况,对于初步了解数据质量非常有用。.describe():生成描述性统计信息,如计数、均值、标准差、最小值、最大值和四分位数,默认只针对数值型列。include='all'可以包含非数值型列。
3. 选择数据
在数据处理中,我们经常需要选择特定的列或行进行操作。pandas提供了多种方式来实现这一点。
print("\n------ 选择数据 ------")
# 选择单列:返回一个series
print("\n选择'姓名'列:")
print(df['姓名'])
# 选择多列:返回一个dataframe
print("\n选择'姓名'和'工资'列:")
print(df[['姓名', '工资']])
# 使用.loc[]按标签选择行和列 (loc[行标签, 列标签])
# 选择第0行到第2行 (包含) 的所有列
print("\n使用.loc[]选择前3行:")
print(df.loc[0:2])
# 选择'张三'和'李四'的'姓名'和'部门' (需要先将姓名设为索引)
# df_indexed_name = df.set_index('姓名')
# print("\n以姓名为索引,选择'张三'和'李四'的'姓名'和'部门':")
# print(df_indexed_name.loc[['张三', '李四'], ['部门', '职位']])
# 使用.iloc[]按位置选择行和列 (iloc[行位置, 列位置])
# 选择第0行到第2行 (不包含) 的所有列
print("\n使用.iloc[]选择前3行:")
print(df.iloc[0:3])
# 选择第0行和第2行,以及第1列和第3列
print("\n使用.iloc[]选择特定行和列 (0,2行;1,3列):")
print(df.iloc[[0, 2], [1, 3]]) # 对应 '姓名', '职位'
解释:
df['列名']:选择单列,返回一个series。df[['列名1', '列名2']]:选择多列,返回一个dataframe。.loc[行标签, 列标签]:主要用于基于标签的索引。行标签可以是单个标签、标签列表或标签切片(包含起始和结束标签)。列标签同理。.iloc[行位置, 列位置]:主要用于基于整数位置的索引。行位置可以是单个整数、整数列表或整数切片(不包含结束位置)。列位置同理。
4. 数据清洗
真实世界的数据往往是不完美的,可能包含缺失值、重复值或错误的数据类型。数据清洗是数据分析的关键步骤。
print("\n------ 数据清洗 ------")
# 检查缺失值
print("\n各列缺失值数量:")
print(df.isnull().sum())
# 填充缺失值 (例如:职位缺失填充为'待定', 绩效等级缺失填充为'd')
df_filled = df.copy() # 创建副本,避免修改原始dataframe
df_filled['职位'].fillna('待定', inplace=true)
df_filled['绩效等级'].fillna('d', inplace=true)
print("\n填充缺失值后的数据:")
print(df_filled)
# 删除包含缺失值的行
df_dropna_rows = df.dropna()
print("\n删除包含缺失值的行后的数据:")
print(df_dropna_rows)
# 删除包含缺失值的列 (如果某一列的缺失值过多)
# df_dropna_cols = df.dropna(axis=1)
# print("\n删除包含缺失值的列后的数据:")
# print(df_dropna_cols)
# 检查重复行
print("\n重复行数量:", df.duplicated().sum())
# 删除重复行
# 为了演示,我们先创建一个有重复行的dataframe
data_with_duplicates = {
'a': [1, 2, 2, 3, 4],
'b': ['x', 'y', 'y', 'z', 'w']
}
df_dup = pd.dataframe(data_with_duplicates)
print("\n原始带重复值数据:\n", df_dup)
df_no_dup = df_dup.drop_duplicates()
print("\n删除重复值后的数据:\n", df_no_dup)
# 数据类型转换 (例如:将'工资'列转换为整数类型)
# 注意:如果列中包含非数字值,转换会报错,需要先处理
df_cleaned = df_filled.copy() # 使用填充过缺失值的df
df_cleaned['工资'] = df_cleaned['工资'].astype(int)
print("\n'工资'列数据类型转换为int后的数据信息:")
df_cleaned.info()
解释:
.isnull().sum():统计每列的缺失值(nan)数量。.fillna(value, inplace=true):用指定的值填充缺失值。inplace=true表示直接修改原dataframe。.dropna(axis=0/1):删除包含缺失值的行(axis=0,默认)或列(axis=1)。.duplicated().sum():检查并统计重复的行。.drop_duplicates():删除重复的行。.astype(dtype):将列的数据类型转换为指定的类型(如int,float,str,datetime等)。
5. 数据排序
对数据进行排序是常见的需求,例如按工资高低、入职时间先后等。
print("\n------ 数据排序 ------")
# 按'工资'列升序排序
df_sorted_salary_asc = df_cleaned.sort_values(by='工资', ascending=true)
print("\n按'工资'升序排序:")
print(df_sorted_salary_asc)
# 按'入职日期'降序排序
df_sorted_date_desc = df_cleaned.sort_values(by='入职日期', ascending=false)
print("\n按'入职日期'降序排序:")
print(df_sorted_date_desc)
# 多列排序:先按'部门'升序,再按'工资'降序
df_sorted_multi = df_cleaned.sort_values(by=['部门', '工资'], ascending=[true, false])
print("\n按'部门'升序,'工资'降序排序:")
print(df_sorted_multi)
解释:
.sort_values(by='列名', ascending=true/false):根据指定列的值进行排序。
by:指定排序的列名,可以是单个列名或列名列表。ascending:布尔值,true为升序(默认),false为降序。如果是多列排序,可以传入布尔值列表,对应每列的排序方式。
6. 数据筛选
数据筛选是根据特定条件从dataframe中选择子集的过程,非常灵活和强大。
print("\n------ 数据筛选 ------")
# 筛选'部门'为'销售部'的员工
sales_employees = df_cleaned[df_cleaned['部门'] == '销售部']
print("\n'销售部'的员工:")
print(sales_employees)
# 筛选'工资'大于等于8000的员工
high_salary_employees = df_cleaned[df_cleaned['工资'] >= 8000]
print("\n工资大于等于8000的员工:")
print(high_salary_employees)
# 多条件筛选:'部门'为'市场部' 且 '绩效等级'为'a'的员工
market_a_employees = df_cleaned[(df_cleaned['部门'] == '市场部') & (df_cleaned['绩效等级'] == 'a')]
print("\n'市场部'且'绩效等级'为'a'的员工:")
print(market_a_employees)
# 多条件筛选:'部门'为'销售部' 或 '部门'为'研发部'的员工
sales_or_rd_employees = df_cleaned[(df_cleaned['部门'] == '销售部') | (df_cleaned['部门'] == '研发部')]
print("\n'销售部'或'研发部'的员工:")
print(sales_or_rd_employees)
# 使用.isin()筛选:'部门'在列表['销售部', '市场部']中的员工
selected_departments = df_cleaned[df_cleaned['部门'].isin(['销售部', '市场部'])]
print("\n部门在['销售部', '市场部']中的员工:")
print(selected_departments)
# 筛选包含特定字符串的行 (例如:职位包含'经理')
# 注意:使用.str访问字符串方法
manager_employees = df_cleaned[df_cleaned['职位'].str.contains('经理', na=false)] # na=false 处理 nan 值
print("\n职位包含'经理'的员工:")
print(manager_employees)
解释:
df[条件]:这是最基本的筛选方式,条件是一个布尔series,dataframe会返回对应true的行。&(与),|(或),~(非):用于组合多个条件。**注意:**在pandas中,条件之间必须使用&、|、~,而不是python原生的and、or、not,并且每个条件表达式都必须用括号括起来。.isin(列表):筛选某列的值是否在给定列表中。.str.contains(字符串, na=false):筛选字符串列中包含特定子串的行。na=false表示将缺失值视为不包含该子串。
7. 应用函数
pandas允许你对dataframe的列或整个dataframe应用函数,进行更复杂的数据转换和计算。
print("\n------ 应用函数 ------")
# 对单列应用函数:例如,计算年终奖 (假设为月工资的2倍)
df_processed = df_cleaned.copy()
df_processed['年终奖'] = df_processed['工资'] * 2
print("\n添加'年终奖'列:")
print(df_processed[['姓名', '工资', '年终奖']])
# 使用apply()对单列应用自定义函数 (例如:将绩效等级转换为数值)
def convert_performance(grade):
if grade == 'a':
return 3
elif grade == 'b':
return 2
elif grade == 'c':
return 1
else: # d或其他
return 0
df_processed['绩效分数'] = df_processed['绩效等级'].apply(convert_performance)
print("\n添加'绩效分数'列:")
print(df_processed[['姓名', '绩效等级', '绩效分数']])
# 使用lambda函数进行快速计算 (例如:计算税前总收入)
df_processed['税前总收入'] = df_processed.apply(lambda row: row['工资'] + row['年终奖'], axis=1)
print("\n添加'税前总收入'列:")
print(df_processed[['姓名', '工资', '年终奖', '税前总收入']])
# 对多列进行批量操作 (例如:所有数值列乘以100)
# numeric_cols = df_processed.select_dtypes(include=['int64', 'float64']).columns
# df_processed[numeric_cols] = df_processed[numeric_cols].apply(lambda x: x * 100)
# print("\n数值列乘以100后的数据 (部分):")
# print(df_processed[numeric_cols].head())
解释:
- 直接运算:对整列进行算术运算,pandas会自动进行元素级操作。
.apply(function, axis=0/1):- 当作用于series时(即dataframe的单列),
function会作用于series的每一个元素。 - 当作用于dataframe时:
axis=0(默认):function会作用于每一列(series)。axis=1:function会作用于每一行(series)。此时,function的参数是每一行的数据(一个series),你可以通过row['列名']访问行中的特定值。
- 当作用于series时(即dataframe的单列),
lambda函数:一种匿名函数,常用于apply()中,进行简单的、一次性的操作。
8. 写入excel文件
完成所有数据处理后,你可能需要将结果保存到新的excel文件中。
print("\n------ 写入excel文件 ------")
output_file_path = '处理后的员工信息.xlsx'
# 将处理后的dataframe写入新的excel文件
# index=false 意味着不将dataframe的索引写入excel的第一列
df_processed.to_excel(output_file_path, index=false)
print(f"\n数据已成功写入 '{output_file_path}'")
# 将多个dataframe写入同一个excel文件的不同工作表
output_multi_sheet_file = '多工作表员工信息.xlsx'
with pd.excelwriter(output_multi_sheet_file) as writer:
df_processed.to_excel(writer, sheet_name='所有员工', index=false)
sales_employees.to_excel(writer, sheet_name='销售部员工', index=false)
high_salary_employees.to_excel(writer, sheet_name='高薪员工', index=false)
print(f"\n多个dataframe已成功写入 '{output_multi_sheet_file}' 的不同工作表")
解释:
.to_excel(file_path, index=false):将dataframe写入excel文件。file_path:输出文件的路径。index=false:非常重要,它告诉pandas不要将dataframe的索引作为一列写入excel文件。如果为true(默认),dataframe的索引会作为第一列被写入,通常这不是我们想要的。
pd.excelwriter():用于在同一个excel文件中写入多个工作表。你可以创建一个excelwriter对象,然后将不同的dataframe写入到不同的sheet_name中。使用with语句可以确保文件在操作完成后正确关闭。
常见问题与技巧
1. 处理大文件
对于非常大的excel文件,一次性加载到内存可能会导致内存溢出。你可以考虑:
chunksize参数:在read_excel()中使用chunksize参数,分块读取数据,逐块处理。
# for chunk in pd.read_excel(file_path, chunksize=1000):
# # 对每个chunk进行处理
# print(f"处理了 {len(chunk)} 行数据")
usecols参数:只读取需要的列,减少内存占用。
# df_partial = pd.read_excel(file_path, usecols=['姓名', '工资', '部门'])
2. 日期格式问题
excel中的日期在pandas中通常会被正确识别为datetime类型。如果发现日期格式不正确,可以使用pd.to_datetime()进行转换。
# df['入职日期'] = pd.to_datetime(df['入职日期'])
3. 编码问题
在读取csv等文本文件时,可能会遇到编码问题。excel文件通常不会有这个问题,但如果出现乱码,可以尝试在read_csv()中使用encoding参数(例如encoding='utf-8'或encoding='gbk')。read_excel()通常会自动处理。
4. 性能优化
对于大规模数据操作,可以考虑:
- 向量化操作:尽可能使用pandas内置的向量化方法(如
df['col'] * 2),而不是循环apply()函数,因为向量化操作通常更快。 - 数据类型优化:使用更节省内存的数据类型,例如将整数列转换为
int16或int32,而不是默认的int64。
总结与展望
通过本篇博客,你已经掌握了使用pandas操作excel的核心技能:从文件的读取、数据的查看,到灵活的选择、深入的清洗、有序的排序、精确的筛选,再到强大的函数应用,最后将处理结果写入新的excel文件。
pandas的强大之处远不止于此,它还提供了数据分组聚合(groupby)、数据合并连接(merge/join)、时间序列分析、数据可视化等高级功能。随着你对pandas的熟练度提高,你将能够解决更复杂的数据处理和分析任务,真正实现办公自动化,大幅提升工作效率。
现在,是时候将这些知识应用到你的实际工作中了! 尝试用pandas解决你日常工作中遇到的excel难题,你会发现一个全新的、高效的数据处理世界。祝你在python自动化办公的道路上越走越远!
以上就是python自动化办公之使用pandas玩转excel数据处理全攻略的详细内容,更多关于python pandas处理excel数据的资料请关注代码网其它相关文章!
发表评论