MATLAB高级数据结构:cell、struct与table深度应用

文章目录


处理复杂数据时,简单的矩阵不够用了。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');

这种组织方式清晰、易于扩展,也方便后续查询和分析。

相关推荐
努力努力再努力wz1 小时前
【Lua入门系列】从 Table 到元表与元方法:一文理解 Lua 的行为扩展机制
开发语言·junit·lua
qq_406981031 小时前
什么是顶层 const什么是底层const
开发语言·c++
星夜离尘561 小时前
MATLAB 刚体坐标变换:点、方向和逆变换为什么不能混用
matlab
Eider19982 小时前
python基础语法之并发基础练习
开发语言·python
#麻辣小龙虾#2 小时前
网页布局css中flex+margin的组合布局技巧
开发语言·前端·javascript
云和数据.ChenGuang2 小时前
python和java的try
java·开发语言·python
我是唐青枫2 小时前
Kotlin Inheritance(继承)详解:语法、原理、实战 Demo
开发语言·kotlin
ly76892 小时前
从 OpenAPI 到多语言 SDK 生成:Java 服务端契约漂移与生成器版本治理
java·开发语言·openapi·java 21·版本兼容·契约漂移·sdk 生成
lqbzlll2 小时前
CVE-2026-91403 排查指南:Java JSSE 信任链漏洞的根因、影响范围和修复步骤
java·开发语言·信任链