4. Pandas数据结构:Series与DataFrame的创建、索引与切片、数据筛选与排序
各位工程师朋友,大家好。今天我们来聊聊Pandas的两个核心数据结构——Series和DataFrame。说实话,我刚接触Pandas那会儿,也觉得不就是个表格嘛,有啥好学的?直到我在处理一批MEMS加速度计的测试数据时,发现用纯Python列表操作,代码又臭又长,调试到半夜。后来用Pandas重写,半小时搞定。嗯,这就是工具的力量。
这一章,我会带着大家从创建、索引、切片,到筛选和排序,一步步把这两个数据结构吃透。你想想看,传感器芯片测试数据动辄几十万行,没有Pandas,你手动去数?不现实。
4.1 Series:一维带标签的数组
Series说白了就是一列数据,每个数据都有一个标签(索引)。我习惯把它想象成Excel里的一列,但比Excel灵活得多。
4.1.1 创建Series
创建Series最简单的方式,就是传一个列表进去。比如我们记录5个温度传感器的读数:
import pandas as pd
# 从列表创建
temp_data = [25.3, 26.1, 24.8, 27.0, 25.9]
s = pd.Series(temp_data)
print(s)
输出是这样的:
0 25.3
1 26.1
2 24.8
3 27.0
4 25.9
dtype: float64
注意看,左边自动生成了0到4的整数索引。但实际项目中,我们更希望用有意义的标签。比如用传感器编号:
s = pd.Series(temp_data, index=['S1', 'S2', 'S3', 'S4', 'S5'])
print(s)
S1 25.3
S2 26.1
S3 24.8
S4 27.0
S5 25.9
dtype: float64
还可以用字典创建,键自动变成索引:
data_dict = {'S1': 25.3, 'S2': 26.1, 'S3': 24.8}
s = pd.Series(data_dict)
4.1.2 索引与切片
Series的索引有两种方式:位置索引和标签索引。这里有个坑,我当年刚学时踩过。
位置索引:用数字,从0开始。
print(s[0]) # 第一个元素
print(s[1:3]) # 第2到第3个元素(左闭右开)
标签索引:用我们自定义的标签。
print(s['S1']) # 标签为'S1'的元素
print(s[['S1','S3']]) # 多个标签
我建议你养成习惯:
.loc[]—— 基于标签索引.iloc[]—— 基于位置索引
print(s.loc['S1']) # 明确用标签
print(s.iloc[0]) # 明确用位置
4.2 DataFrame:二维表格数据结构
DataFrame才是我们真正干活的主力。它就像一张Excel表格,有行有列。每个传感器芯片的测试数据,通常就是一张DataFrame。
4.2.1 创建DataFrame
最常见的创建方式是从字典创建。比如我们记录一批压力传感器的测试结果:
data = {
'传感器ID': ['P001', 'P002', 'P003', 'P004'],
'量程(MPa)': [10, 20, 10, 50],
'精度(%)': [0.5, 0.2, 0.5, 0.1],
'输出(mV)': [100.2, 200.5, 99.8, 501.3],
'合格': [True, True, False, True]
}
df = pd.DataFrame(data)
print(df)
输出:
传感器ID 量程(MPa) 精度(%) 输出(mV) 合格
0 P001 10 0.5 100.2 True
1 P002 20 0.2 200.5 True
2 P003 10 0.5 99.8 False
3 P004 50 0.1 501.3 True
你看,自动生成了行索引0,1,2,3。列名就是字典的键。
也可以从CSV文件读取,这是实际项目中最常用的:
df = pd.read_csv('sensor_test_data.csv')
4.2.2 索引与切片
DataFrame的索引和切片比Series复杂一些,但掌握了规律就很简单。
列索引:
# 取单列,返回Series
print(df['传感器ID'])
# 取多列,返回DataFrame
print(df[['传感器ID', '输出(mV)']])
行索引(切片):
# 前两行
print(df[0:2])
# 用标签索引(如果行索引是自定义的)
print(df.loc[0:2]) # 注意:loc是闭区间
print(df.iloc[0:2]) # iloc是左闭右开
行列同时索引:
# 取第1行第2列
print(df.iloc[0, 1])
# 取传感器ID为P002的精度和输出
print(df.loc[df['传感器ID'] == 'P002', ['精度(%)', '输出(mV)']])
df[(df['量程'] > 10) & (df['合格'] == True)],括号不能省。每个条件都要用括号括起来,这是血的教训。
4.3 数据筛选
数据筛选是测试数据分析中最常用的操作。说白了,就是从海量数据中找出我们关心的那部分。
4.3.1 布尔索引
这是最直观的筛选方式。比如找出所有不合格的传感器:
fail_df = df[df['合格'] == False]
print(fail_df)
输出:
传感器ID 量程(MPa) 精度(%) 输出(mV) 合格
2 P003 10 0.5 99.8 False
多条件筛选:
# 量程大于10且精度小于0.5的传感器
result = df[(df['量程(MPa)'] > 10) & (df['精度(%)'] < 0.5)]
print(result)
4.3.2 使用isin()方法
当我们需要筛选多个特定值时,用isin()比多个or条件更简洁:
# 筛选传感器ID为P001和P003的数据
selected = df[df['传感器ID'].isin(['P001', 'P003'])]
4.3.3 使用query()方法
我个人很喜欢query(),因为它写起来更像SQL,可读性更好:
# 等价于上面的多条件筛选
result = df.query('量程(MPa) > 10 and 精度(%) < 0.5')
4.4 数据排序
排序也是家常便饭。比如按输出值从小到大排,或者按量程从大到小排。
4.4.1 按单列排序
# 按输出值升序
df_sorted = df.sort_values(by='输出(mV)')
print(df_sorted)
# 按输出值降序
df_sorted_desc = df.sort_values(by='输出(mV)', ascending=False)
4.4.2 按多列排序
先按量程升序,量程相同的再按精度降序:
df_sorted_multi = df.sort_values(by=['量程(MPa)', '精度(%)'], ascending=[True, False])
4.4.3 按索引排序
# 按行索引排序
df_sorted_index = df.sort_index()
# 按列名排序
df_sorted_columns = df.sort_index(axis=1)
df.reset_index(drop=True) 可以重置为连续的整数索引。drop=True表示丢弃原来的索引列。
4.5 知识体系结构图
下面这张图,是我自己总结的Pandas数据结构核心逻辑。你看一遍,心里就有谱了。
4.6 实战小案例:传感器测试数据快速分析
最后,我给大家一个完整的实战片段。假设我们有一批压力传感器的测试数据,需要找出量程在20MPa以上、精度优于0.3%的合格传感器,并按输出值降序排列。
import pandas as pd
# 模拟数据
data = {
'传感器ID': ['P001', 'P002', 'P003', 'P004', 'P005'],
'量程(MPa)': [10, 20, 30, 50, 10],
'精度(%)': [0.5, 0.2, 0.3, 0.1, 0.8],
'输出(mV)': [100.2, 200.5, 301.0, 501.3, 99.5],
'合格': [True, True, True, True, False]
}
df = pd.DataFrame(data)
# 筛选:量程>=20,精度<=0.3,合格
result = df.query('量程(MPa) >= 20 and 精度(%) <= 0.3 and 合格 == True')
# 按输出值降序
result_sorted = result.sort_values(by='输出(mV)', ascending=False)
print(result_sorted)
输出:
传感器ID 量程(MPa) 精度(%) 输出(mV) 合格
3 P004 50 0.1 501.3 True
2 P003 30 0.3 301.0 True
1 P002 20 0.2 200.5 True
你看,三行代码就搞定了。如果用手工在Excel里筛,得折腾好几分钟,还容易出错。
好了,这一章就到这里。记住,多动手敲代码,光看是学不会的。下次见。