如果把pandas比作一座房子的骨架,Series是一根根柱子,DataFrame就是由柱子搭建起来的整个房间。理解这两种结构,你就掌握了数据清洗的通用语言。
文中涉及到的数据文件可以联系我发给你,因为我还不知道怎么在公众号插入文件
pandas 是Python数据清洗的核心库。它的名字源自"面板数据"(Panel Data),最早由Wes McKinney于2008年创建,如今已成为全球数据科学家日常使用最频繁的Python库之一。
为什么pandas能成为数据清洗的事实标准?
一句话总结:在Python生态中,pandas之于表格数据,就像Word之于文档——它就是你处理和清洗数据的默认工具。
本系列的所有代码都将围绕pandas展开。让我们从它最基础的两个数据结构开始。
Series 是pandas中最基本的数据结构,你可以把它理解成"带标签的一维数组"。Excel表格中的一列,本质上就是一个Series。
import pandas as pdimport numpy as np# 从列表创建,默认索引从0开始s1 = pd.Series([22969, 6315, 3222, 4518, 5176])print(s1)输出:
0 229691 63152 32223 45184 5176dtype: int64左边那一列数字(0, 1, 2...)就是索引(index),右边是值(values)。索引可以自定义:
# 自定义索引,让每个值拥有一个有意义的标签salary = pd.Series( [22969, 6315, 3222, 4518, 5176], index=['EMP0001', 'EMP0002', 'EMP0003', 'EMP0004', 'EMP0005'], name='薪资')print(salary)EMP0001 22969EMP0002 6315EMP0003 3222EMP0004 4518EMP0005 5176Name: 薪资, dtype: int64print(salary.values) # 值: [22969 6315 3222 4518 5176]print(salary.index) # 索引: Index(['EMP0001', ..., 'EMP0005'])print(salary.dtype) # 数据类型: int64print(salary.name) # Series名称: 薪资Series支持类似numpy数组的向量化操作,这是它比Python列表强大得多的地方:
salary * 1.2 # 所有薪资乘以1.2(年终奖系数)salary.mean() # 求均值salary.max() # 求最大值salary.describe() # 一次性获得所有描述性统计关键理解:Series的运算是对所有元素同时进行的(向量化),不需要写for循环。这既是性能优势,也是代码简洁的根源。
DataFrame 是由多个Series按列组合而成的二维表格,是pandas中最核心、最常用的数据结构。你可以把它看作Excel的一个工作表,或者SQL的一张表。
方法一:从字典创建(最常用)
df = pd.DataFrame({ '姓名': ['张三', '李四', '王五'], '年龄': [28, 35, 42], '部门': ['技术部', '市场部', '运营部'], '薪资': [12000, 9000, 15000]})print(df)方法二:从列表嵌套创建
data = [ ['张三', 28, '技术部', 12000], ['李四', 35, '市场部', 9000], ['王五', 42, '运营部', 15000]]df = pd.DataFrame(data, columns=['姓名', '年龄', '部门', '薪资'])方法三:从numpy数组创建
arr = np.array([ [28, 12000], [35, 9000], [42, 15000]])df = pd.DataFrame(arr, columns=['年龄', '薪资'])三种方法殊途同归,选择你最顺手的方式即可。从字典创建是最直观、最推荐的方式。
拿到一个DataFrame后,第一件事就是了解它的基本信息。以下是每次必须查看的属性:
# 读取真实数据来演示df = pd.read_csv('data_python/employee_data.csv')df.shape # (500, 8) —— 500行,8列df.columns # Index(['emp_id', 'name', 'department', ...])df.index # RangeIndex(start=0, stop=500, step=1)df.dtypes # 每一列的数据类型df.values # 底层的numpy数组df.shape | ||
df.columns | ||
df.index | ||
df.dtypes | ||
df.values |
新手提示:
shape和dtypes是两个最重要的属性。拿到数据第一步先看shape确认数据量,再看dtypes确认每列的类型是否和你预期一致。
df.head() # 默认显示前5行df.head(10) # 显示前10行df.tail() # 默认显示后5行df.tail(3) # 显示最后3行这两个方法让你快速"瞥一眼"数据长什么样,不需要打印整个表格。
df.info()输出示例:
<class 'pandas.core.frame.DataFrame'>RangeIndex: 500 entries, 0 to 499Data columns (total 8 columns): # Column Non-Null Count Dtype--- ------ -------------- ----- 0 emp_id 500 non-null object 1 name 500 non-null object 2 department 450 non-null object 3 gender 500 non-null object 4 age 495 non-null float64 5 education 475 non-null object 6 hire_date 500 non-null object 7 salary 488 non-null float64从 Non-Null Count 这一列,你能立刻发现哪些字段存在缺失值——这是数据清洗的起点。
df.describe()输出包括 count(计数)、mean(均值)、std(标准差)、min(最小值)、25%/50%/75%分位数、max(最大值)。
实用技巧:如果
describe()中某列的min或max数值看起来很不合理(比如年龄出现200),那很可能存在异常值——这是我们后面要重点处理的问题。
索引是DataFrame的行标签,相当于Excel的行号,但它可以自定义为任何有意义的值。
# 默认索引是 RangeIndex(0, 1, 2, ...)print(df.index)# 将 emp_id 设为索引df2 = df.set_index('emp_id')print(df2.index)# 通过索引取值print(df2.loc['EMP0001']) # 用loc通过标签取值print(df.iloc[0]) # 用iloc通过位置取值(第0行)loc 和 iloc 的区别是最基础也最容易混淆的知识点:
df.loc[] | df.loc['EMP0001'] | |
df.iloc[] | df.iloc[0] | |
df.loc[:, 'salary'] | ||
df.iloc[:, 7] |
现在,让我们用刚学的函数来浏览本系列的6个练习数据集:
import pandas as pdfrom pathlib import Pathdata_dir = Path('data_python')# 遍历所有数据集,打印基本信息for file in sorted(data_dir.glob('*.csv')): df = pd.read_csv(file) print(f"{file.name:30s} | shape: {str(df.shape):12s} | columns: {list(df.columns)}")输出:
customer_info.csv | shape: (300, 7) | columns: ['customer_id', 'full_name', ...]department_data.csv | shape: (5, 5) | columns: ['department', 'dept_code', ...]employee_data.csv | shape: (500, 8) | columns: ['emp_id', 'name', ...]sales_orders.csv | shape: (610, 6) | columns: ['order_id', 'order_date', ...]survey_data.csv | shape: (400, 6) | columns: ['respondent_id', 'age_group', ...]time_series_sales.csv | shape: (471, 5) | columns: ['date', 'product_id', ...]这就是我们用一行代码对6套数据做的"全身扫描"。接下来深入学习每个数据集的细节:
emp = pd.read_csv('data_python/employee_data.csv')sales = pd.read_csv('data_python/sales_orders.csv')cust = pd.read_csv('data_python/customer_info.csv')print("=" * 50)print("员工数据 .info()")emp.info()print("\n" + "=" * 50)print("销售数据 .head(3)")print(sales.head(3))print("\n" + "=" * 50)print("客户数据 .describe()")print(cust.describe())你会在输出中看到缺失值、奇怪的数据类型(比如日期被识别为object)、以及异常的范围——这些问题为后续的清洗练习做好了铺垫。
今天你掌握了pandas最核心的两个数据结构:
pd.Series([...]) | pd.DataFrame({...}) | |
.shape.dtype | .shape.dtypes, .columns | |
.head().describe() | .head().tail(), .info() | |
s[0]s['label'] | .loc[].iloc[] |
你现在已经拥有读懂任何pandas代码的基础能力。下一章,我们将进入实战的第一环——把数据读进来。
下一篇 《数据读取与写入》 将教你如何读取各种格式的数据文件:CSV的编码问题如何解决?Excel工作表如何选择?数据清洗完成后如何保存?还有中文字符乱码的终极解决方案。打好地基,准备动手!
#Pandas #DataFrame #Series #Python数据结构 #数据分析入门 #Pandas教程
觉得有用?分享给和你一样在学习数据分析的朋友。评论区留下你的问题,下一篇文章就可能回答你。