文章目录
处理复杂数据时,简单的矩阵不够用了。MATLAB提供了cell单元数组、struct结构体、table表格等高级数据结构,掌握它们能让数据组织更清晰,代码更易维护。
cell单元数组:存储异构数据
cell的核心特点是每个元素可以是不同类型、不同大小的数据。
创建cell数组:
matlab
% 直接定义
c = {42, 'hello', [1 2 3], true, @sin};
% 预分配(性能更好)
c = cell(3, 4); % 3行4列的空cell数组
% 从已有数据创建
fileList = {'exp1.csv', 'exp2.csv', 'exp3.csv'};
访问cell元素:
matlab
c = {10, 'text', [1 2 3; 4 5 6]};
% 花括号:取出内容本身
c{1} % 10(数值)
c{2} % 'text'(字符数组)
c{3} % 2x3矩阵
% 圆括号:取出一个子cell数组
c(1:2) % 1x2的cell,包含10和'text'
二维cell:
matlab
data = cell(3, 2);
data{1,1} = '张三'; data{1,2} = 88;
data{2,1} = '李四'; data{2,2} = 92;
data{3,1} = '王五'; data{3,2} = 76;
% 访问
data{2,1} % '李四'
data(:,2) % 返回3x1的cell,包含三个成绩
[data{:,2}] % 展开所有成绩为向量:[88 92 76]
实际应用场景:
matlab
% 1. 批量存储不同长度的向量
results = cell(5, 1);
for i = 1:5
len = randi([50, 150]);
results{i} = randn(1, len); % 每个长度不同
end
% 2. 存储文件名列表
files = dir('*.csv');
fileNames = {files.name}; % 提取所有文件名到cell
% 3. 函数返回值的集合
methods = {'linear', 'spline', 'pchip'};
errors = cell(size(methods));
for k = 1:length(methods)
errors{k} = testInterpolation(methods{k});
end
struct结构体:按字段组织数据
结构体用字段名(field)存储数据,逻辑清晰,适合描述有多个属性的对象。
创建结构体:
matlab
% 直接赋值创建
s.name = '实验A';
s.date = datetime('2024-06-15');
s.temperature = 25.3;
s.data = randn(100, 3);
% 一次性创建
s = struct('name', '实验A', 'date', datetime('2024-06-15'), ...
'temperature', 25.3, 'data', randn(100,3));
访问和修改:
matlab
s.name % 读取字段
s.name = '实验B'; % 修改字段
% 动态字段名(字段名存在变量里)
fieldName = 'temperature';
s.(fieldName) % 等价于 s.temperature
% 检查字段是否存在
if isfield(s, 'data')
disp('data字段存在')
end
% 列出所有字段
fieldnames(s) % 返回cell数组:{'name'; 'date'; 'temperature'; 'data'}
结构体数组(重要):
matlab
% 创建结构体数组
for i = 1:5
experiments(i).id = i;
experiments(i).date = datetime('2024-01-01') + days(i);
experiments(i).result = randn(10, 1);
experiments(i).passed = (mean(experiments(i).result) > 0);
end
% 访问第3个实验的结果
experiments(3).result
% 提取所有实验的id(返回向量)
[experiments.id] % [1 2 3 4 5]
% 提取通过状态
[experiments.passed] % 逻辑向量
% 筛选通过的实验
passed_exp = experiments([experiments.passed]);
嵌套结构体:
matlab
project.name = '温控系统测试';
project.config.sampleRate = 1000;
project.config.duration = 60;
project.config.channels = {'temp', 'pressure', 'flow'};
project.results.rawData = randn(60000, 3);
project.results.stats.mean = mean(project.results.rawData);
project.results.stats.std = std(project.results.rawData);
% 访问
project.config.sampleRate % 1000
project.results.stats.mean % 1x3向量
实战:用结构体管理参数:
matlab
function output = processSignal(signal, params)
% params结构体包含所有可调参数
if ~isfield(params, 'filterOrder')
params.filterOrder = 4; % 默认值
end
if ~isfield(params, 'cutoffFreq')
params.cutoffFreq = 50;
end
% 使用参数
[b, a] = butter(params.filterOrder, params.cutoffFreq/(params.fs/2));
output = filtfilt(b, a, signal);
end
% 调用
params.fs = 1000;
params.filterOrder = 5;
params.cutoffFreq = 60;
filtered = processSignal(rawData, params);
这种方式比传一堆散装参数清晰得多,后期扩展也方便。
table:专为表格数据设计
table是R2013b引入的,专门处理表格型数据(类似Excel表格或数据库表)。
创建table:
matlab
% 从列向量创建
name = {'张三'; '李四'; '王五'; '赵六'};
age = [22; 25; 28; 24];
score = [88.5; 92.0; 76.3; 85.7];
gender = categorical({'男'; '男'; '女'; '男'});
T = table(name, age, score, gender);
% 显示表格
T
输出效果:
name age score gender
______ ___ _____ ______
'张三' 22 88.5 男
'李四' 25 92 男
'王五' 28 76.3 女
'赵六' 24 85.7 男
按列名访问:
matlab
T.score % 提取score列(数值向量)
T.name{2} % '李四'
% 添加新列
T.grade = T.score / 100;
% 重命名列
T.Properties.VariableNames{'score'} = 'finalScore';
按条件筛选行:
matlab
% 找出成绩大于85的学生
T(T.score > 85, :)
% 找出男性且成绩大于80的
T(T.gender == '男' & T.score > 80, :)
% 排序
T_sorted = sortrows(T, 'score', 'descend'); % 按成绩降序
% 提取多列
T(:, {'name', 'score'})
与Excel交互:
matlab
% 从Excel读取
T = readtable('student_data.xlsx');
% 指定sheet和范围
T = readtable('data.xlsx', 'Sheet', 'Sheet2', 'Range', 'A1:D100');
% 写入Excel
writetable(T, 'output.xlsx', 'Sheet', 'Results');
% 追加到已有文件
writetable(T, 'output.xlsx', 'Sheet', 'NewData', 'WriteMode', 'append');
分组统计(类似SQL的GROUP BY):
matlab
% 按性别分组,计算平均分
G = groupsummary(T, 'gender', 'mean', 'score')
table的优势:
- 列可以有名字,代码可读性高
- 支持不同类型的列(数值、字符、分类、日期)
- 内置排序、筛选、分组功能
- 与Excel、CSV无缝交互
categorical分类数组
处理离散类别数据时,categorical比字符串高效:
matlab
% 创建分类变量
gender = categorical({'男', '女', '男', '女', '男'});
% 查看类别
categories(gender) % {'女'; '男'}
% 指定类别顺序(用于排序)
size_cat = categorical({'中', '大', '小', '中', '大'}, ...
{'小', '中', '大'}, 'Ordinal', true);
sort(size_cat) % 按小-中-大顺序排序
% 统计各类别数量
summary(gender)
% 男: 3
% 女: 2
% 重新编码
gender = renamecats(gender, {'男', '女'}, {'M', 'F'});
categorical在table里用得很多,节省内存且支持有序比较。
datetime时间数组
时间序列数据分析必备:
matlab
% 创建时间点
t1 = datetime('2024-06-15 14:30:00', 'InputFormat', 'yyyy-MM-dd HH:mm:ss');
t2 = datetime('now');
% 时间序列
t = datetime(2024, 1, 1) + hours(0:23); % 2024年1月1日每小时
% 时间差(duration类型)
dt = t2 - t1;
days(dt) % 相差多少天
hours(dt) % 相差多少小时
% 格式化显示
datestr(t1, 'yyyy-mm-dd HH:MM:SS')
实际应用:时间序列表格:
matlab
time = datetime(2024,1,1) + minutes(0:10:1440-1); % 每10分钟
temp = 20 + 5*sin(2*pi*(1:144)/144) + randn(1,144)*0.5;
T = timetable(time', temp');
T.Properties.VariableNames = {'Temperature'};
% 重采样到每小时
T_hourly = retime(T, 'hourly', 'mean');
% 查询特定时间段
T(T.time >= datetime(2024,1,1,8,0,0) & T.time < datetime(2024,1,1,18,0,0), :)
数据结构选择指南
| 场景 | 推荐结构 | 原因 |
|---|---|---|
| 存储不同长度的向量 | cell | 每个元素大小可以不同 |
| 实验参数配置 | struct | 字段名清晰,逻辑分明 |
| 批量实验结果 | 结构体数组 | 每个实验一个结构体,易于遍历和筛选 |
| Excel表格数据 | table | 天然支持列名、筛选、排序 |
| 分类变量 | categorical | 内存效率高,支持有序比较 |
| 时间序列数据 | timetable | 自带时间索引,支持重采样 |
| 简单数值计算 | 矩阵 | 速度最快,函数支持最全 |
综合实战案例
matlab
% 从多个CSV文件读取实验数据,整理成统一格式
files = dir('exp_*.csv');
% 用结构体数组存储
experiments = struct('file', {}, 'data', {}, 'stats', {});
for k = 1:length(files)
% 读取数据
T = readtable(fullfile(files(k).folder, files(k).name));
% 填充结构体
experiments(k).file = files(k).name;
experiments(k).data = T;
experiments(k).stats.mean = mean(T.value);
experiments(k).stats.std = std(T.value);
experiments(k).stats.n = height(T);
fprintf('处理完成:%s,均值=%.4f\n', files(k).name, experiments(k).stats.mean);
end
% 汇总统计结果到table
summaryTable = struct2table([experiments.stats]);
summaryTable.fileName = {experiments.file}';
% 保存汇总结果
writetable(summaryTable, 'summary_report.xlsx');
这种组织方式清晰、易于扩展,也方便后续查询和分析。