3. 表格变量访问与索引操作
在 MATLAB 中,table 是一种为“列向异构数据”设计的容器:每一列是一个变量,可以拥有自己的类型(数值、字符串、分类、日期时间、元胞等),但所有变量共享相同的行数。正因为这种“按列组织”的结构,table 的索引体系比普通数值矩阵更丰富,也更容易混淆。本节围绕三种括号与点号访问方式展开,并给出子集提取与快速查看的实用方法。
三种索引符号的分工
理解 table 索引的关键,是先分清“你要拿到的是子表、变量内容,还是变量容器”。MATLAB 用三种符号表达这三种意图:
- 圆括号
T(rows, vars):返回一个新的 table(子表),保留变量名与类型。行、列位置都可以用数字、逻辑向量、变量名或:指定。 - 点号
T.VarName:直接取出某一列的数据内容,返回该变量本身的类型(数值列返回数值向量,字符串列返回 string 数组)。这是最常用的取数方式。 - 花括号
T{rows, vars}:取出内容并尝试拼接为矩阵或元胞数组,适合需要把多列数值合并成一个数值矩阵参与运算的场合。
一个常见的误区是把 T(:, 2) 与 T{:, 2} 混用。前者得到的是只含一个变量的 table,直接参与算术运算会报错;后者得到的是该列的原始数值向量,可以直接计算。判断标准很简单:要保留表格结构就用圆括号,要拿数据本身就用点号或花括号。
行、列与变量子集的提取
实际处理数据时,最常见的需求是“按条件筛行、按名称选列”。行方向可以用逻辑向量表达条件,例如从一张学生成绩表中取出不及格记录:
T = table([1;2;3;4], ["A";"B";"C";"D"], [88;92;75;96], ...
'VariableNames', ["ID","Name","Score"]);
lowScore = T(T.Score < 90, :); % 逻辑索引筛行,保留全部变量
nameScore = T(:, ["Name","Score"]); % 按变量名选列
sub = T(2:3, ["Name","Score"]); % 行区间 + 列名组合
这里 T.Score < 90 生成逻辑向量 [1;0;1;0],作为行下标传入圆括号,得到只含 A、C 两行的子表。列方向推荐使用变量名字符串数组而非列序号,因为变量名在增删列后依然稳定,可读性也更好。若变量名含空格或特殊字符,需写成 T.("Total Score") 形式。
需要提醒的是,table 的行下标与变量下标是两套独立维度,写 T(1, 1) 得到的是“第 1 行第 1 个变量”构成的 1×1 子表,而不是一个标量。若确实想取单个单元格的值,应使用 T{1, 1} 或 T.ID(1)。
head、tail 与 summary 的快速查看
面对几十列、上万行的表,先“看几眼”再动手,是避免索引错误的有效习惯。三个函数各有侧重:
| 函数 | 作用 | 典型用途 |
|---|---|---|
head(T, n) | 显示前 n 行(默认 8 行) | 确认变量名、数据类型与前几行取值格式 |
tail(T, n) | 显示后 n 行 | 检查数据尾部是否有缺失、异常或截断 |
summary(T) | 逐变量给出类型与统计摘要 | 快速判断哪些列是数值、哪些含缺失、取值范围是否合理 |
summary 对数值变量给出最小值、中位数、最大值,对分类变量给出各类别计数,对含缺失的列会明确标出缺失数量。它不改变数据,只是把“表的结构画像”打印出来,非常适合在写筛选条件之前先确认列名拼写和类型是否符合预期。
一个完整的筛选与核对流程
假设要统计成绩不低于 90 分的学生平均分,并保留其姓名。合理的操作顺序是:先用 summary(T) 确认 Score 为数值列且无缺失;再用逻辑索引筛行;最后用点号取列计算均值。
summary(T) % 确认 Score 为 double,无缺失
pass = T(T.Score >= 90, :); % 子表:B、D 两行
avgScore = mean(pass.Score); % 点号取列,直接求均值 → 94
names = pass.Name; % 字符串列,返回 string 数组
若把最后一步误写成 mean(pass(:, "Score")),MATLAB 会对 table 求均值而报类型错误,这正是圆括号与点号分工的体现。养成“筛选用圆括号、计算用点号”的习惯,可以规避大部分 table 索引问题。
T.(varName) 动态访问;批量选列时用 T(:, varNames) 传入字符串数组,比逐个点号访问更简洁。T{rows, vars} 在所选列类型不一致时会返回元胞数组而非矩阵,后续运算前应先检查 class 结果,避免隐式转换带来的意外。