2. Pandas入门:DataFrame与Series结构,从CSV/TXT加载仿真数据

做仿真数据处理,说白了就是跟表格打交道。MATLAB里我们用table,Python里就是Pandas。我个人习惯把Pandas叫做“Python界的Excel”,但比Excel快得多,也灵活得多。

这一章,咱们就搞定两个核心数据结构:Series和DataFrame。然后直接从CSV和TXT文件里把仿真数据拽进来。

2.1 两个核心结构:Series和DataFrame

先别急着敲代码,咱们把概念理清楚。

结构 类比 特点
Series Excel里的一列 带标签的一维数组,每个元素有索引
DataFrame Excel里的整个表格 二维结构,多列Series组成,有行索引和列名

你想想看,仿真数据里最常见的场景是什么?时间序列、电压值、电流值。每一列就是一个Series,所有列拼在一起就是DataFrame。

核心记忆点:DataFrame = 多个Series的集合,共享同一个行索引。

2.2 创建Series和DataFrame

咱们直接上手。先创建一个Series:

import pandas as pd

# 从列表创建Series
voltage = pd.Series([3.3, 3.31, 3.29, 3.32, 3.30])
print(voltage)

输出长这样:

0    3.30
1    3.31
2    3.29
3    3.32
4    3.30
dtype: float64

左边是索引,右边是值。默认索引从0开始,但你可以自己指定:

time = pd.Series([0.0, 0.1, 0.2, 0.3, 0.4], index=['t0', 't1', 't2', 't3', 't4'])
print(time)

DataFrame的创建更常用。我一般用字典来创建:

data = {
    'time_ms': [0.0, 0.1, 0.2, 0.3, 0.4],
    'voltage_V': [3.30, 3.31, 3.29, 3.32, 3.30],
    'current_A': [0.12, 0.13, 0.11, 0.14, 0.12]
}
df = pd.DataFrame(data)
print(df)

输出:

   time_ms  voltage_V  current_A
0      0.0       3.30       0.12
1      0.1       3.31       0.13
2      0.2       3.29       0.11
3      0.3       3.32       0.14
4      0.4       3.30       0.12

嗯,这里要注意:字典的键变成了列名,值变成了列数据。整齐得很。

2.3 从CSV加载仿真数据

这才是咱们的重头戏。仿真软件导出的数据,十有八九是CSV格式。我遇到过很多次,同事导出来的CSV文件编码不对、分隔符不是逗号、表头有多余行……各种坑。

标准加载方式:

df = pd.read_csv('simulation_results.csv')
print(df.head())  # 只看前5行

但现实往往不这么美好。咱们看看常用参数:

参数 作用 常用值
sep 指定分隔符 ','(默认)、'\t'、';'
header 指定表头行 0(第一行)、None(无表头)
skiprows 跳过前N行 2、[0,2,3]
encoding 文件编码 'utf-8'、'gbk'、'latin1'
na_values 指定缺失值标记 ['NA', 'null', '-999']

我曾经踩过的坑:有一次从某国产仿真软件导出CSV,默认编码是gbk,直接用read_csv报错。后来加了encoding='gbk'才搞定。如果你遇到UnicodeDecodeError,先试试encoding='latin1',基本能通吃。

实战案例——加载一个带注释的仿真数据文件:

df = pd.read_csv(
    'motor_sim.csv',
    skiprows=2,          # 跳过前两行注释
    sep=',',             # 逗号分隔
    encoding='utf-8',
    na_values=['NaN', 'inf', '-inf']
)

2.4 从TXT加载仿真数据

TXT文件其实跟CSV差不多,只是分隔符更自由。常见的有空格分隔、制表符分隔、固定宽度。

空格分隔的TXT:

df = pd.read_csv('data.txt', sep='\s+', header=None)

sep='\s+'表示一个或多个空白字符,非常实用。

制表符分隔:

df = pd.read_csv('data.tsv', sep='\t')

固定宽度文件:

df = pd.read_fwf('fixed_width.txt', widths=[8, 12, 10])

小技巧:不确定文件格式时,先用文本编辑器打开看一眼。我习惯用head -20 data.txt(Linux/Mac)或直接在VS Code里预览前20行。看清楚分隔符和表头再写代码,省得反复试错。

2.5 知识结构图

下面这张图把本章的核心逻辑串起来了:

Pandas入门:数据结构与数据加载 仿真数据文件 CSV / TXT 其他格式 pd.read_csv() / pd.read_fwf() 参数:sep, header, encoding DataFrame(二维表格) Series(一维列数据) df.head() / df.info() df['列名'] / df.iloc[] Series运算 / 统计 核心流程:仿真文件 → 加载函数 → DataFrame/Series → 数据查看与预处理 注意:分隔符、编码、表头行是加载时最容易出错的三个地方

2.6 数据加载后的快速检查

数据加载进来,别急着分析。先做三件事:

  1. 看形状:df.shape——返回(行数, 列数)
  2. 看信息:df.info()——列名、非空数量、数据类型
  3. 看头尾:df.head()和df.tail()——确认数据是否正确

我每次加载完数据,第一件事就是跑df.info()。它能快速暴露问题:比如某列本该是数值型,结果显示object,说明里面有非数字字符。

# 快速检查套路
print("数据形状:", df.shape)
print("\n列名:", df.columns.tolist())
print("\n数据类型:")
print(df.dtypes)
print("\n前3行:")
print(df.head(3))

避坑指南:如果某列是时间数据,记得用pd.to_datetime()转换。我曾经因为没转换时间列,后面做时序分析时全乱套了。

2.7 实战:加载一个真实的仿真数据

假设你有一个仿真结果文件step_response.csv,内容如下:

# Step Response Data
# Time(ms), Voltage(V), Current(mA)
0.0, 0.0, 0.0
0.1, 1.2, 5.3
0.2, 2.8, 8.7
0.3, 3.9, 10.2
0.4, 4.5, 10.8
0.5, 4.8, 11.0

加载代码:

df = pd.read_csv(
    'step_response.csv',
    skiprows=2,          # 跳过注释行
    names=['time_ms', 'voltage_V', 'current_mA']  # 自定义列名
)
print(df)

输出:

   time_ms  voltage_V  current_mA
0      0.0        0.0         0.0
1      0.1        1.2         5.3
2      0.2        2.8         8.7
3      0.3        3.9        10.2
4      0.4        4.5        10.8
5      0.5        4.8        11.0

干净利落。接下来你就可以用这些数据做分析、画图、甚至直接传给MATLAB联调。

嗯,这一章的内容就到这里。Pandas的DataFrame和Series是后续所有操作的基础,CSV/TXT加载是数据入门的第一个关卡。把这两个东西练熟,后面的路就好走了。