MATLAB - 数据导入
MATLAB 中的现代数据导入
Section titled “MATLAB 中的现代数据导入”数据导入是大多数数据分析工作流程中的第一步。MATLAB 提供了一套强大而灵活的工具,用于从各种文件格式加载数据。虽然旧方法侧重于通用函数,但现代 MATLAB 鼓励使用针对特定数据类型量身定制的专业高性能函数,主要是用于表格数据的 readtable 和用于数值数组的 readmatrix。
现代方法:高级 I/O 函数
Section titled “现代方法:高级 I/O 函数”对于大多数常见任务,您应该优先选择 MATLAB 的高级导入函数。它们经过性能优化,自动处理许多常见的格式问题,并将数据以方便的现代数据结构(如 table 表格和 matrix 矩阵)返回。
| 函数 | 最佳用途 |
|---|---|
readtable | 表格数据(例如 CSV、TXT、XLSX)的推荐函数。它可以推断数据类型,处理缺失值,并将数据读取到 table 中,从而保留列标题和混合数据类型。 |
readmatrix | 非常适合包含纯数值、矩阵式数据的文件。在这些情况下,它比 readtable 更快,并返回一个标准的数值矩阵。 |
readcell | 当您拥有混合数据但需要保留文件的原始单元格结构,而不需要 table 的结构化组织时使用。 |
importdata | 一个多功能通用函数,可以处理多种文件类型,包括图像和文本文件。它是一个很好的备用选择,但与专用函数相比,有时会产生较不规范的输出格式。 |
webread | 从 RESTful Web 服务和网页读取内容。对于集成在线 API 数据至关重要。 |
示例 1:使用 readtable 导入表格数据
Section titled “示例 1:使用 readtable 导入表格数据”让我们导入一个带有列标题的文本文件。这是最常见的数据导入任务。考虑一个名为 weeklydata.csv 的文件,其内容如下:
Day,Temperature,HumidityMonday,22.5,55Tuesday,24.1,52Wednesday,23.8,58Thursday,25.0,60Friday,21.9,49现代方法是使用 readtable。它会自动检测分隔符(逗号),识别标题行,并解析数值数据。
% 最佳实践:使用 fullfile 创建平台无关的路径% 确保 'weeklydata.csv' 位于您当前的 MATLAB 路径中。filename = 'weeklydata.csv';
% 使用 try-catch 块进行健壮的错误处理try % readtable 自动检测标题和分隔符 dataTable = readtable(filename);
% 显示导入的表格 disp('Successfully imported data as a table:'); disp(dataTable);
% 访问数据是直观的 fprintf('\nMean Temperature: %.2f\n', mean(dataTable.Temperature));
catch ME % 提供用户友好的错误消息 fprintf('Error importing file: %s\n', ME.message);end当你运行该文件时,readtable 将返回一个 table 变量,这是 MATLAB 中处理混合类型列数据的现代标准。输出将是:
Successfully imported data as a table: Day Temperature Humidity ___________ ___________ ________
"Monday" 22.5 55 "Tuesday" 24.1 52 "Wednesday" 23.8 58 "Thursday" 25 60 "Friday" 21.9 49
Mean Temperature: 23.46示例 2:使用 importdata 导入图像
Section titled “示例 2:使用 importdata 导入图像”importdata 仍然非常适用于非表格数据,如图像。对于图像特定任务,图像处理工具箱(Image Processing Toolbox™)中的函数,如 imread 甚至更好,但 importdata 对于快速加载非常有用。
% 确保图像文件(例如 'peppers.png',一个标准的 MATLAB 演示图像)可用。filename = 'peppers.png';
try imageData = importdata(filename);
% `image` 函数适用于快速显示。 % 如需更多控制,请使用 `imshow`。 figure; % 创建一个新的图形窗口 imshow(imageData); title(['Image: ', filename], 'Interpreter', 'none');
catch ME fprintf('Could not load or display image. Error: %s\n', ME.message);end低级文件 I/O:实现最大控制
Section titled “低级文件 I/O:实现最大控制”低级文件 I/O 函数,如 fopen、fscanf 和 fclose,让您完全控制数据读取过程。仅当高级函数失效时才应使用它们,例如处理非标准文件格式、具有复杂结构的二进制文件,或者需要通过逐行读取文件来最小化内存使用时。
最佳实践:始终使用带有 finally 子句的 try-catch 块,以确保即使在读取过程中发生错误,fclose 也能被调用。这可以防止文件句柄保持打开状态。
主要的低级函数有:
| 函数 | 描述 |
|---|---|
| fopen | 打开文件,或获取关于已打开文件的信息。返回一个文件标识符。 |
| fclose | 关闭一个或所有打开的文件。对于防止资源泄露至关重要。 |
| fgetl | 从文件中读取单行文本,丢弃换行符。 |
| textscan | 将数据从文本文件或字符串读取到单元格数组中。比 fscanf 更强大、更灵活。 |
| fread | 从二进制文件读取数据到矩阵中。 |
| fwrite | 将数据写入二进制文件。 |
| fprintf | 将格式化数据写入文本文件。 |
示例 3:使用 textscan 进行低级 I/O
Section titled “示例 3:使用 textscan 进行低级 I/O”让我们回顾一下原始教程中的降雨数据 (myfile.txt)。使用 fscanf 手动解析此数据既复杂又容易出错。一种更健壮的现代方法是使用 fgetl 跳过标题,并使用 textscan 读取结构化数据。
/* myfile.txt 内容 */Rainfall DataMonths: June, July, August
M = 312:00:00June-201217.21 28.52 39.78 16.55 23.6719.15 0.35 17.57 NaN 12.01...以下是解析此文件的一种更现代、更安全的方法。
filename = 'myfile.txt';fid = -1; % 初始化文件 ID 为无效值
try fid = fopen(filename, 'r'); if fid == -1 error('CannotOpenFile', 'Could not open the file: %s', filename); end
% 跳过前 3 行标题 for i = 1:3, fgetl(fid); end
% 读取月份数 headerLine = fgetl(fid); numMonths = sscanf(headerLine, 'M = %d');
% 预分配结构体数组以提高效率 myData(numMonths) = struct('time', [], 'month', [], 'raindata', []);
% 定义数值数据块的格式(5 列浮点数) formatSpec = '%f %f %f %f %f';
for n = 1:numMonths fgetl(fid); % 跳过空行 myData(n).time = fgetl(fid); myData(n).month = fgetl(fid); % 使用 textscan 读取接下来的 7 行数值数据 dataBlock = textscan(fid, formatSpec, 7, 'CollectOutput', true); myData(n).raindata = dataBlock{1}; end
disp('Data successfully parsed using low-level I/O.'); disp(myData);
catch ME fprintf(2, 'An error occurred: %s\n', ME.message);
finally % 无论是否发生错误,此块都将执行 if fid ~= -1 fclose(fid); disp('File closed.'); endend常见错误和调试技巧
Section titled “常见错误和调试技巧”- 错误:文件未找到。 检查文件是否在当前 MATLAB 文件夹或 MATLAB 路径中。使用
pwd查看当前文件夹,并使用exist(filename, 'file')检查文件是否对 MATLAB 可见。 - 错误:数据类型或列不正确。 如果
readtable错误地解释了您的数据,请使用其选项来指定变量名、类型和范围。使用'Delimiter'和'HeaderLines'名称-值对。 - 性能:大文件导入缓慢。 对于非常大的文本文件,
readmatrix通常比readtable更快。对于内存无法完全加载的文件,请使用datastore以分块方式处理数据。 - 低级 I/O:未关闭的文件。 忘记调用
fclose(fid)会锁定文件并消耗系统资源。务必使用try-catch-finally结构来确保文件被关闭。