1\]Goldberger, A., Amaral, L., Glass, L., Hausdorff, J., Ivanov, P. C., Mark, R., ... \& Stanley, H. E. (2000). PhysioBank, PhysioToolkit, and PhysioNet: Components of a new research resource for complex physiologic signals. Circulation \[Online\]. 101 (23), pp. e215--e220. RRID:SCR_007345. SHA256SUMS.txt文件同样中记录了各个文件的命名,但需要调整细节,否则将报错: ```Matlab % 文件路径 filePath = 'D:\ECG-Tran\mit-bih-arrhythmia-database\SHA256SUMS.txt'; % 读取所有行 fid = fopen(filePath, 'r'); lines = textscan(fid, '%s', 'Delimiter', '\n', 'Whitespace', ''); fclose(fid); lines = lines{1}; % 提取每行末尾的文件名 fileNames = {}; for i = 1:length(lines) token = regexp(lines{i}, '\S+$', 'match', 'once'); if ~isempty(token) fileNames{end+1} = token; end end % 提取扩展名(包括短横线,如 '.hea-'),无扩展名的留空 extensions = cellfun(@(f) regexp(f, '\.[^.]*$', 'match', 'once'), fileNames, 'UniformOutput', false); % 将空后缀替换为 'no_extension' emptyIdx = cellfun(@isempty, extensions); extensions(emptyIdx) = {'no_extension'}; % 获取唯一扩展名及其对应的合法字段名 uniqueExt = unique(extensions); fieldNames = cellfun(@ext2fieldname, uniqueExt, 'UniformOutput', false); % 分组并排序 sortedGroups = struct(); extOriginalMap = struct(); % 存储每个字段名对应的原始扩展名(用于显示) for i = 1:length(uniqueExt) ext = uniqueExt{i}; fieldName = fieldNames{i}; idx = strcmp(extensions, ext); groupFiles = fileNames(idx); % 排序:优先按文件名开头的数字升序,否则按字母序 nums = cellfun(@(f) regexp(f, '^\d+', 'match', 'once'), groupFiles, 'UniformOutput', false); hasNum = ~cellfun(@isempty, nums); if all(hasNum) numVals = cellfun(@str2double, nums); [~, sortIdx] = sort(numVals); else [~, sortIdx] = sort(groupFiles); end sortedGroups.(fieldName) = groupFiles(sortIdx); extOriginalMap.(fieldName) = ext; % 保存原始扩展名 % 保存为 MAT 文件 save('sorted_filenames_by_ext.mat', 'sortedGroups', 'extOriginalMap'); end % 显示结果(使用原始扩展名展示) extFieldNames = fieldnames(sortedGroups); for i = 1:length(extFieldNames) fieldName = extFieldNames{i}; originalExt = extOriginalMap.(fieldName); if strcmp(originalExt, 'no_extension') displayExt = '无扩展名'; else displayExt = originalExt; end fprintf('后缀: %s, 共 %d 个文件\n', displayExt, length(sortedGroups.(fieldName))); disp(sortedGroups.(fieldName)'); end % 将扩展名转换为合法的结构体字段名(例如 '.atr' -> 'atr', '.hea-' -> 'hea_') function validName = ext2fieldname(ext) if strcmp(ext, 'no_extension') validName = 'no_extension'; return; end % 去掉开头的点号 if startsWith(ext, '.') ext = ext(2:end); end % 将非字母数字下划线替换为下划线(例如 '-' -> '_') validName = regexprep(ext, '[^a-zA-Z0-9_]', '_'); % 如果结果为空或首字符是数字,则添加前缀 'ext_' if isempty(validName) || ismember(validName(1), '0123456789') validName = ['ext_' validName]; end end ``` 这里的文件相较于前文使用的数据库要更多了: ```Matlab 后缀: .1, 共 1 个文件 {'mitdbdir/src/tab.1'} 后缀: .2, 共 1 个文件 {'mitdbdir/src/tab.2'} 后缀: .3, 共 1 个文件 {'mitdbdir/src/tab.3'} 后缀: .4, 共 1 个文件 {'mitdbdir/src/tab.4'} 后缀: .5, 共 1 个文件 {'mitdbdir/src/tab.5'} 后缀: .at_, 共 8 个文件 {'108.at_'} {'117.at_'} {'119.at_'} {'203.at_'} {'209.at_'} {'214.at_'} {'215.at_'} {'222.at_'} 后缀: .atr, 共 72 个文件 {'100.atr' } {'101.atr' } {'102-0.atr' } {'102.atr' } {'103.atr' } {'104.atr' } {'105.atr' } {'106.atr' } {'107.atr' } {'108.atr' } {'109.atr' } {'111.atr' } {'112.atr' } {'113.atr' } {'114.atr' } {'115.atr' } {'116.atr' } {'117.atr' } {'118.atr' } {'119.atr' } {'121.atr' } {'122.atr' } {'123.atr' } {'124.atr' } {'200.atr' } {'201.atr' } {'202.atr' } {'203.atr' } {'205.atr' } {'207.atr' } {'208.atr' } {'209.atr' } {'210.atr' } {'212.atr' } {'213.atr' } {'214.atr' } {'215.atr' } {'217.atr' } {'219.atr' } {'220.atr' } {'221.atr' } {'222.atr' } {'223.atr' } {'228.atr' } {'230.atr' } {'231.atr' } {'232.atr' } {'233.atr' } {'234.atr' } {'x_mitdb/x_108.atr'} {'x_mitdb/x_109.atr'} {'x_mitdb/x_111.atr'} {'x_mitdb/x_112.atr'} {'x_mitdb/x_113.atr'} {'x_mitdb/x_114.atr'} {'x_mitdb/x_115.atr'} {'x_mitdb/x_116.atr'} {'x_mitdb/x_117.atr'} {'x_mitdb/x_121.atr'} {'x_mitdb/x_122.atr'} {'x_mitdb/x_123.atr'} {'x_mitdb/x_124.atr'} {'x_mitdb/x_220.atr'} {'x_mitdb/x_221.atr'} {'x_mitdb/x_222.atr'} {'x_mitdb/x_223.atr'} {'x_mitdb/x_228.atr'} {'x_mitdb/x_230.atr'} {'x_mitdb/x_231.atr'} {'x_mitdb/x_232.atr'} {'x_mitdb/x_233.atr'} {'x_mitdb/x_234.atr'} 后缀: .bat, 共 1 个文件 {'mitdbdir/src/printdir.bat'} 后缀: .c, 共 3 个文件 {'mitdbdir/src/dbnotes-html.c'} {'mitdbdir/src/dbnotes.c' } {'mitdbdir/src/dbtab.c' } 后缀: .dat, 共 71 个文件 {'100.dat' } {'101.dat' } {'102.dat' } {'103.dat' } {'104.dat' } {'105.dat' } {'106.dat' } {'107.dat' } {'108.dat' } {'109.dat' } {'111.dat' } {'112.dat' } {'113.dat' } {'114.dat' } {'115.dat' } {'116.dat' } {'117.dat' } {'118.dat' } {'119.dat' } {'121.dat' } {'122.dat' } {'123.dat' } {'124.dat' } {'200.dat' } {'201.dat' } {'202.dat' } {'203.dat' } {'205.dat' } {'207.dat' } {'208.dat' } {'209.dat' } {'210.dat' } {'212.dat' } {'213.dat' } {'214.dat' } {'215.dat' } {'217.dat' } {'219.dat' } {'220.dat' } {'221.dat' } {'222.dat' } {'223.dat' } {'228.dat' } {'230.dat' } {'231.dat' } {'232.dat' } {'233.dat' } {'234.dat' } {'x_mitdb/x_108.dat'} {'x_mitdb/x_109.dat'} {'x_mitdb/x_111.dat'} {'x_mitdb/x_112.dat'} {'x_mitdb/x_113.dat'} {'x_mitdb/x_114.dat'} {'x_mitdb/x_115.dat'} {'x_mitdb/x_116.dat'} {'x_mitdb/x_117.dat'} {'x_mitdb/x_121.dat'} {'x_mitdb/x_122.dat'} {'x_mitdb/x_123.dat'} {'x_mitdb/x_124.dat'} {'x_mitdb/x_220.dat'} {'x_mitdb/x_221.dat'} {'x_mitdb/x_222.dat'} {'x_mitdb/x_223.dat'} {'x_mitdb/x_228.dat'} {'x_mitdb/x_230.dat'} {'x_mitdb/x_231.dat'} {'x_mitdb/x_232.dat'} {'x_mitdb/x_233.dat'} {'x_mitdb/x_234.dat'} 后缀: .dvi, 共 1 个文件 {'mitdbdir/src/title.dvi'} 后缀: .gz, 共 9 个文件 {'mitdbdir/src/contents.gz'} {'mitdbdir/src/cover.gz' } {'mitdbdir/src/extext.gz' } {'mitdbdir/src/fdtext.gz' } {'mitdbdir/src/index.gz' } {'mitdbdir/src/intro.gz' } {'mitdbdir/src/notes.gz' } {'mitdbdir/src/tables.gz' } {'mitdbdir/src/title.gz' } 后缀: .h, 共 1 个文件 {'mitdbdir/src/notes.h'} 后缀: .hea, 共 71 个文件 {'100.hea' } {'101.hea' } {'102.hea' } {'103.hea' } {'104.hea' } {'105.hea' } {'106.hea' } {'107.hea' } {'108.hea' } {'109.hea' } {'111.hea' } {'112.hea' } {'113.hea' } {'114.hea' } {'115.hea' } {'116.hea' } {'117.hea' } {'118.hea' } {'119.hea' } {'121.hea' } {'122.hea' } {'123.hea' } {'124.hea' } {'200.hea' } {'201.hea' } {'202.hea' } {'203.hea' } {'205.hea' } {'207.hea' } {'208.hea' } {'209.hea' } {'210.hea' } {'212.hea' } {'213.hea' } {'214.hea' } {'215.hea' } {'217.hea' } {'219.hea' } {'220.hea' } {'221.hea' } {'222.hea' } {'223.hea' } {'228.hea' } {'230.hea' } {'231.hea' } {'232.hea' } {'233.hea' } {'234.hea' } {'x_mitdb/x_108.hea'} {'x_mitdb/x_109.hea'} {'x_mitdb/x_111.hea'} {'x_mitdb/x_112.hea'} {'x_mitdb/x_113.hea'} {'x_mitdb/x_114.hea'} {'x_mitdb/x_115.hea'} {'x_mitdb/x_116.hea'} {'x_mitdb/x_117.hea'} {'x_mitdb/x_121.hea'} {'x_mitdb/x_122.hea'} {'x_mitdb/x_123.hea'} {'x_mitdb/x_124.hea'} {'x_mitdb/x_220.hea'} {'x_mitdb/x_221.hea'} {'x_mitdb/x_222.hea'} {'x_mitdb/x_223.hea'} {'x_mitdb/x_228.hea'} {'x_mitdb/x_230.hea'} {'x_mitdb/x_231.hea'} {'x_mitdb/x_232.hea'} {'x_mitdb/x_233.hea'} {'x_mitdb/x_234.hea'} 后缀: .htm, 共 5 个文件 {'mitdbdir/foreword.htm'} {'mitdbdir/intro.htm' } {'mitdbdir/mitdbdir.htm'} {'mitdbdir/records.htm' } {'mitdbdir/tables.htm' } 后缀: .pl, 共 1 个文件 {'mitdbdir/src/makelinks.pl'} 后缀: .tr, 共 6 个文件 {'mitdbdir/src/contents.tr'} {'mitdbdir/src/cover.tr' } {'mitdbdir/src/extext.tr' } {'mitdbdir/src/fdtext.tr' } {'mitdbdir/src/index.tr' } {'mitdbdir/src/intro.tr' } 后缀: .xws, 共 439 个文件 {'100.xws' } {'101.xws' } {'102.xws' } {'103.xws' } {'104.xws' } {'105.xws' } {'106.xws' } {'107.xws' } {'108.xws' } {'109.xws' } {'111.xws' } {'112.xws' } {'113.xws' } {'114.xws' } {'115.xws' } {'116.xws' } {'117.xws' } {'118.xws' } {'119.xws' } {'121.xws' } {'122.xws' } {'123.xws' } {'124.xws' } {'200.xws' } {'201.xws' } {'202.xws' } {'203.xws' } {'205.xws' } {'207.xws' } {'208.xws' } {'209.xws' } {'210.xws' } {'212.xws' } {'213.xws' } {'214.xws' } {'215.xws' } {'217.xws' } {'219.xws' } {'220.xws' } {'221.xws' } {'222.xws' } {'223.xws' } {'228.xws' } {'230.xws' } {'231.xws' } {'232.xws' } {'233.xws' } {'234.xws' } {'mitdbdir/samples/1001103.xws'} {'mitdbdir/samples/1002513.xws'} {'mitdbdir/samples/1002609.xws'} {'mitdbdir/samples/1002755.xws'} {'mitdbdir/samples/1010134.xws'} {'mitdbdir/samples/1010148.xws'} {'mitdbdir/samples/1010513.xws'} {'mitdbdir/samples/1010954.xws'} {'mitdbdir/samples/1012432.xws'} {'mitdbdir/samples/1020055.xws'} {'mitdbdir/samples/1020112.xws'} {'mitdbdir/samples/1020128.xws'} {'mitdbdir/samples/1020230.xws'} {'mitdbdir/samples/1020451.xws'} {'mitdbdir/samples/1020935.xws'} {'mitdbdir/samples/1021612.xws'} {'mitdbdir/samples/1030109.xws'} {'mitdbdir/samples/1031721.xws'} {'mitdbdir/samples/1031915.xws'} {'mitdbdir/samples/1032213.xws'} {'mitdbdir/samples/1032333.xws'} {'mitdbdir/samples/1032858.xws'} {'mitdbdir/samples/1040342.xws'} {'mitdbdir/samples/1040513.xws'} {'mitdbdir/samples/1040552.xws'} {'mitdbdir/samples/1040617.xws'} {'mitdbdir/samples/1040822.xws'} {'mitdbdir/samples/1042651.xws'} {'mitdbdir/samples/1042910.xws'} {'mitdbdir/samples/1050527.xws'} {'mitdbdir/samples/1050757.xws'} {'mitdbdir/samples/1051516.xws'} {'mitdbdir/samples/1051752.xws'} {'mitdbdir/samples/1052202.xws'} {'mitdbdir/samples/1052645.xws'} {'mitdbdir/samples/1052727.xws'} {'mitdbdir/samples/1052808.xws'} {'mitdbdir/samples/1052907.xws'} {'mitdbdir/samples/1060019.xws'} {'mitdbdir/samples/1060137.xws'} {'mitdbdir/samples/1060253.xws'} {'mitdbdir/samples/1060423.xws'} {'mitdbdir/samples/1060757.xws'} {'mitdbdir/samples/1061052.xws'} {'mitdbdir/samples/1061227.xws'} {'mitdbdir/samples/1061617.xws'} {'mitdbdir/samples/1062513.xws'} {'mitdbdir/samples/1062552.xws'} {'mitdbdir/samples/1070044.xws'} {'mitdbdir/samples/1071230.xws'} {'mitdbdir/samples/1071954.xws'} {'mitdbdir/samples/1072038.xws'} {'mitdbdir/samples/1072552.xws'} {'mitdbdir/samples/1080022.xws'} {'mitdbdir/samples/1080451.xws'} {'mitdbdir/samples/1080741.xws'} {'mitdbdir/samples/1080813.xws'} {'mitdbdir/samples/1081055.xws'} {'mitdbdir/samples/1081808.xws'} {'mitdbdir/samples/1082005.xws'} {'mitdbdir/samples/1082420.xws'} {'mitdbdir/samples/1082810.xws'} {'mitdbdir/samples/1082900.xws'} {'mitdbdir/samples/1090013.xws'} {'mitdbdir/samples/1090128.xws'} {'mitdbdir/samples/1090336.xws'} {'mitdbdir/samples/1090446.xws'} {'mitdbdir/samples/1090527.xws'} {'mitdbdir/samples/1091401.xws'} {'mitdbdir/samples/1091713.xws'} {'mitdbdir/samples/1091921.xws'} {'mitdbdir/samples/1092609.xws'} {'mitdbdir/samples/1092803.xws'} {'mitdbdir/samples/1092828.xws'} {'mitdbdir/samples/1092910.xws'} {'mitdbdir/samples/1110025.xws'} {'mitdbdir/samples/1110241.xws'} {'mitdbdir/samples/1110352.xws'} {'mitdbdir/samples/1110404.xws'} {'mitdbdir/samples/1110831.xws'} {'mitdbdir/samples/1111153.xws'} {'mitdbdir/samples/1111541.xws'} {'mitdbdir/samples/1111954.xws'} {'mitdbdir/samples/1112702.xws'} {'mitdbdir/samples/1121140.xws'} {'mitdbdir/samples/1121230.xws'} {'mitdbdir/samples/1121249.xws'} {'mitdbdir/samples/1130420.xws'} {'mitdbdir/samples/1130822.xws'} {'mitdbdir/samples/1131148.xws'} {'mitdbdir/samples/1131227.xws'} {'mitdbdir/samples/1132210.xws'} {'mitdbdir/samples/1132901.xws'} {'mitdbdir/samples/1140000.xws'} {'mitdbdir/samples/1140120.xws'} {'mitdbdir/samples/1140339.xws'} {'mitdbdir/samples/1140356.xws'} {'mitdbdir/samples/1140435.xws'} {'mitdbdir/samples/1140536.xws'} {'mitdbdir/samples/1140831.xws'} {'mitdbdir/samples/1140926.xws'} {'mitdbdir/samples/1141137.xws'} {'mitdbdir/samples/1142002.xws'} {'mitdbdir/samples/1142929.xws'} {'mitdbdir/samples/1150055.xws'} {'mitdbdir/samples/1150322.xws'} {'mitdbdir/samples/1151552.xws'} {'mitdbdir/samples/1152128.xws'} {'mitdbdir/samples/1152705.xws'} {'mitdbdir/samples/1152842.xws'} {'mitdbdir/samples/1160044.xws'} {'mitdbdir/samples/1160131.xws'} {'mitdbdir/samples/1161000.xws'} {'mitdbdir/samples/1161232.xws'} {'mitdbdir/samples/1161637.xws'} {'mitdbdir/samples/1162308.xws'} {'mitdbdir/samples/1162547.xws'} {'mitdbdir/samples/1170356.xws'} {'mitdbdir/samples/1171158.xws'} {'mitdbdir/samples/1172227.xws'} {'mitdbdir/samples/1180339.xws'} {'mitdbdir/samples/1180831.xws'} {'mitdbdir/samples/1180923.xws'} {'mitdbdir/samples/1181347.xws'} {'mitdbdir/samples/1182232.xws'} {'mitdbdir/samples/1182325.xws'} {'mitdbdir/samples/1182541.xws'} {'mitdbdir/samples/1182623.xws'} {'mitdbdir/samples/1182648.xws'} {'mitdbdir/samples/1182858.xws'} {'mitdbdir/samples/1182953.xws'} {'mitdbdir/samples/1190155.xws'} {'mitdbdir/samples/1190238.xws'} {'mitdbdir/samples/1190451.xws'} {'mitdbdir/samples/1190842.xws'} {'mitdbdir/samples/1192005.xws'} {'mitdbdir/samples/1192533.xws'} {'mitdbdir/samples/1210106.xws'} {'mitdbdir/samples/1210333.xws'} {'mitdbdir/samples/1211648.xws'} {'mitdbdir/samples/1212432.xws'} {'mitdbdir/samples/1212601.xws'} {'mitdbdir/samples/1220109.xws'} {'mitdbdir/samples/1221347.xws'} {'mitdbdir/samples/1222825.xws'} {'mitdbdir/samples/1232210.xws'} {'mitdbdir/samples/1232511.xws'} {'mitdbdir/samples/1232741.xws'} {'mitdbdir/samples/1232836.xws'} {'mitdbdir/samples/1240443.xws'} {'mitdbdir/samples/1240509.xws'} {'mitdbdir/samples/1240521.xws'} {'mitdbdir/samples/1240905.xws'} {'mitdbdir/samples/1241027.xws'} {'mitdbdir/samples/1241738.xws'} {'mitdbdir/samples/1242013.xws'} {'mitdbdir/samples/1242322.xws'} {'mitdbdir/samples/1242603.xws'} {'mitdbdir/samples/1242741.xws'} {'mitdbdir/samples/2000142.xws'} {'mitdbdir/samples/2000538.xws'} {'mitdbdir/samples/2001814.xws'} {'mitdbdir/samples/2002052.xws'} {'mitdbdir/samples/2002449.xws'} {'mitdbdir/samples/2002612.xws'} {'mitdbdir/samples/2002831.xws'} {'mitdbdir/samples/2002901.xws'} {'mitdbdir/samples/2002918.xws'} {'mitdbdir/samples/2002951.xws'} {'mitdbdir/samples/2010000.xws'} {'mitdbdir/samples/2010615.xws'} {'mitdbdir/samples/2010752.xws'} {'mitdbdir/samples/2010853.xws'} {'mitdbdir/samples/2011814.xws'} {'mitdbdir/samples/2012016.xws'} {'mitdbdir/samples/2012233.xws'} {'mitdbdir/samples/2012350.xws'} {'mitdbdir/samples/2012415.xws'} {'mitdbdir/samples/2012519.xws'} {'mitdbdir/samples/2012620.xws'} {'mitdbdir/samples/2012803.xws'} {'mitdbdir/samples/2021016.xws'} {'mitdbdir/samples/2021224.xws'} {'mitdbdir/samples/2021241.xws'} {'mitdbdir/samples/2021822.xws'} {'mitdbdir/samples/2021845.xws'} {'mitdbdir/samples/2021859.xws'} {'mitdbdir/samples/2022110.xws'} {'mitdbdir/samples/2022126.xws'} {'mitdbdir/samples/2022213.xws'} {'mitdbdir/samples/2022558.xws'} {'mitdbdir/samples/2022755.xws'} {'mitdbdir/samples/2022935.xws'} {'mitdbdir/samples/2030500.xws'} {'mitdbdir/samples/2031314.xws'} {'mitdbdir/samples/2031502.xws'} {'mitdbdir/samples/2032202.xws'} {'mitdbdir/samples/2032325.xws'} {'mitdbdir/samples/2032404.xws'} {'mitdbdir/samples/2032446.xws'} {'mitdbdir/samples/2032639.xws'} {'mitdbdir/samples/2032651.xws'} {'mitdbdir/samples/2032715.xws'} {'mitdbdir/samples/2050457.xws'} {'mitdbdir/samples/2051454.xws'} {'mitdbdir/samples/2051522.xws'} {'mitdbdir/samples/2051603.xws'} {'mitdbdir/samples/2051615.xws'} {'mitdbdir/samples/2051957.xws'} {'mitdbdir/samples/2052418.xws'} {'mitdbdir/samples/2052430.xws'} {'mitdbdir/samples/2052757.xws'} {'mitdbdir/samples/2070000.xws'} {'mitdbdir/samples/2070033.xws'} {'mitdbdir/samples/2070045.xws'} {'mitdbdir/samples/2070057.xws'} {'mitdbdir/samples/2070128.xws'} {'mitdbdir/samples/2070207.xws'} {'mitdbdir/samples/2070241.xws'} {'mitdbdir/samples/2070425.xws'} {'mitdbdir/samples/2070519.xws'} {'mitdbdir/samples/2070656.xws'} {'mitdbdir/samples/2071735.xws'} {'mitdbdir/samples/2072536.xws'} {'mitdbdir/samples/2072610.xws'} {'mitdbdir/samples/2072714.xws'} {'mitdbdir/samples/2072910.xws'} {'mitdbdir/samples/2081457.xws'} {'mitdbdir/samples/2081702.xws'} {'mitdbdir/samples/2081910.xws'} {'mitdbdir/samples/2082106.xws'} {'mitdbdir/samples/2082300.xws'} {'mitdbdir/samples/2082808.xws'} {'mitdbdir/samples/2082858.xws'} {'mitdbdir/samples/2082937.xws'} {'mitdbdir/samples/2090047.xws'} {'mitdbdir/samples/2090550.xws'} {'mitdbdir/samples/2091257.xws'} {'mitdbdir/samples/2091421.xws'} {'mitdbdir/samples/2092325.xws'} {'mitdbdir/samples/2092817.xws'} {'mitdbdir/samples/2092833.xws'} {'mitdbdir/samples/2092910.xws'} {'mitdbdir/samples/2100347.xws'} {'mitdbdir/samples/2100656.xws'} {'mitdbdir/samples/2101314.xws'} {'mitdbdir/samples/2101555.xws'} {'mitdbdir/samples/2101732.xws'} {'mitdbdir/samples/2101757.xws'} {'mitdbdir/samples/2102033.xws'} {'mitdbdir/samples/2102915.xws'} {'mitdbdir/samples/2120005.xws'} {'mitdbdir/samples/2121842.xws'} {'mitdbdir/samples/2122421.xws'} {'mitdbdir/samples/2122438.xws'} {'mitdbdir/samples/2122645.xws'} {'mitdbdir/samples/2122846.xws'} {'mitdbdir/samples/2130339.xws'} {'mitdbdir/samples/2131448.xws'} {'mitdbdir/samples/2131505.xws'} {'mitdbdir/samples/2131538.xws'} {'mitdbdir/samples/2131730.xws'} {'mitdbdir/samples/2131755.xws'} {'mitdbdir/samples/2132443.xws'} {'mitdbdir/samples/2132558.xws'} {'mitdbdir/samples/2132651.xws'} {'mitdbdir/samples/2132856.xws'} {'mitdbdir/samples/2140030.xws'} {'mitdbdir/samples/2140221.xws'} {'mitdbdir/samples/2140235.xws'} {'mitdbdir/samples/2140325.xws'} {'mitdbdir/samples/2140356.xws'} {'mitdbdir/samples/2140508.xws'} {'mitdbdir/samples/2140538.xws'} {'mitdbdir/samples/2141353.xws'} {'mitdbdir/samples/2142317.xws'} {'mitdbdir/samples/2142752.xws'} {'mitdbdir/samples/2150255.xws'} {'mitdbdir/samples/2150311.xws'} {'mitdbdir/samples/2150946.xws'} {'mitdbdir/samples/2151558.xws'} {'mitdbdir/samples/2152025.xws'} {'mitdbdir/samples/2152216.xws'} {'mitdbdir/samples/2152457.xws'} {'mitdbdir/samples/2152730.xws'} {'mitdbdir/samples/2152757.xws'} {'mitdbdir/samples/2152942.xws'} {'mitdbdir/samples/2170000.xws'} {'mitdbdir/samples/2170033.xws'} {'mitdbdir/samples/2170123.xws'} {'mitdbdir/samples/2170418.xws'} {'mitdbdir/samples/2170612.xws'} {'mitdbdir/samples/2170651.xws'} {'mitdbdir/samples/2170705.xws'} {'mitdbdir/samples/2171227.xws'} {'mitdbdir/samples/2171401.xws'} {'mitdbdir/samples/2171530.xws'} {'mitdbdir/samples/2171656.xws'} {'mitdbdir/samples/2172227.xws'} {'mitdbdir/samples/2190249.xws'} {'mitdbdir/samples/2190508.xws'} {'mitdbdir/samples/2190522.xws'} {'mitdbdir/samples/2191350.xws'} {'mitdbdir/samples/2191900.xws'} {'mitdbdir/samples/2191957.xws'} {'mitdbdir/samples/2192211.xws'} {'mitdbdir/samples/2192243.xws'} {'mitdbdir/samples/2192443.xws'} {'mitdbdir/samples/2192609.xws'} {'mitdbdir/samples/2192855.xws'} {'mitdbdir/samples/2200646.xws'} {'mitdbdir/samples/2201041.xws'} {'mitdbdir/samples/2201810.xws'} {'mitdbdir/samples/2202029.xws'} {'mitdbdir/samples/2202358.xws'} {'mitdbdir/samples/2202544.xws'} {'mitdbdir/samples/2202940.xws'} {'mitdbdir/samples/2210000.xws'} {'mitdbdir/samples/2210243.xws'} {'mitdbdir/samples/2211300.xws'} {'mitdbdir/samples/2211356.xws'} {'mitdbdir/samples/2211749.xws'} {'mitdbdir/samples/2211912.xws'} {'mitdbdir/samples/2211942.xws'} {'mitdbdir/samples/2212044.xws'} {'mitdbdir/samples/2220645.xws'} {'mitdbdir/samples/2221732.xws'} {'mitdbdir/samples/2221948.xws'} {'mitdbdir/samples/2222007.xws'} {'mitdbdir/samples/2222232.xws'} {'mitdbdir/samples/2222443.xws'} {'mitdbdir/samples/2222543.xws'} {'mitdbdir/samples/2222609.xws'} {'mitdbdir/samples/2230935.xws'} {'mitdbdir/samples/2231235.xws'} {'mitdbdir/samples/2231339.xws'} {'mitdbdir/samples/2231351.xws'} {'mitdbdir/samples/2231721.xws'} {'mitdbdir/samples/2231755.xws'} {'mitdbdir/samples/2231907.xws'} {'mitdbdir/samples/2232358.xws'} {'mitdbdir/samples/2232547.xws'} {'mitdbdir/samples/2232916.xws'} {'mitdbdir/samples/2232951.xws'} {'mitdbdir/samples/2280019.xws'} {'mitdbdir/samples/2280038.xws'} {'mitdbdir/samples/2280050.xws'} {'mitdbdir/samples/2280435.xws'} {'mitdbdir/samples/2281918.xws'} {'mitdbdir/samples/2282008.xws'} {'mitdbdir/samples/2282137.xws'} {'mitdbdir/samples/2282149.xws'} {'mitdbdir/samples/2282642.xws'} {'mitdbdir/samples/2300000.xws'} {'mitdbdir/samples/2300012.xws'} {'mitdbdir/samples/2300511.xws'} {'mitdbdir/samples/2300926.xws'} {'mitdbdir/samples/2302904.xws'} {'mitdbdir/samples/2310002.xws'} {'mitdbdir/samples/2310224.xws'} {'mitdbdir/samples/2312011.xws'} {'mitdbdir/samples/2312110.xws'} {'mitdbdir/samples/2312322.xws'} {'mitdbdir/samples/2320058.xws'} {'mitdbdir/samples/2320151.xws'} {'mitdbdir/samples/2321151.xws'} {'mitdbdir/samples/2321306.xws'} {'mitdbdir/samples/2321509.xws'} {'mitdbdir/samples/2321817.xws'} {'mitdbdir/samples/2322231.xws'} {'mitdbdir/samples/2322247.xws'} {'mitdbdir/samples/2322320.xws'} {'mitdbdir/samples/2322334.xws'} {'mitdbdir/samples/2322353.xws'} {'mitdbdir/samples/2330011.xws'} {'mitdbdir/samples/2330025.xws'} {'mitdbdir/samples/2330218.xws'} {'mitdbdir/samples/2330243.xws'} {'mitdbdir/samples/2330339.xws'} {'mitdbdir/samples/2330502.xws'} {'mitdbdir/samples/2330943.xws'} {'mitdbdir/samples/2331620.xws'} {'mitdbdir/samples/2331802.xws'} {'mitdbdir/samples/2332223.xws'} {'mitdbdir/samples/2340016.xws'} {'mitdbdir/samples/2340637.xws'} {'mitdbdir/samples/2341401.xws'} {'mitdbdir/samples/2341426.xws'} {'mitdbdir/samples/2341702.xws'} {'mitdbdir/samples/2342126.xws'} {'mitdbdir/samples/2342317.xws'} 后缀: 无扩展名, 共 10 个文件 {'ANNOTATORS' } {'RECORDS' } {'mitdbdir/src/domit' } {'mitdbdir/src/exlist' } {'mitdbdir/src/extest' } {'mitdbdir/src/fdlist' } {'mitdbdir/src/makefile' } {'mitdbdir/src/makefile-html'} {'x_mitdb/ANNOTATORS' } {'x_mitdb/RECORDS' } ``` 但我发现一个问题:官方称含48 个充分标注的30分钟长度2导联ECG,但我们可以看出其有71个data文件。多了23个,具体是前缀多了个x,如:x_234.dat和234.dat,但没有资料说明有什么具体区别。 通过可视化观察一下: ```Matlab % 脚本:compare_x234_234.m % 比较 x_234 和 234 记录经过 readdata 处理后的心电图信号 clear; close all; % 数据文件夹路径 dataFolder = 'D:\ECG-Tran\mit-bih-arrhythmia-database\'; % 确保文件夹以文件分隔符结尾 if ~endsWith(dataFolder, filesep) dataFolder = [dataFolder, filesep]; end recordA = '234'; recordB = 'x_234'; fprintf('正在读取记录 %s ...\n', recordA); try [sigA, FsA] = readdata(recordA, dataFolder); catch ME_A warning('readdata 读取 %s 失败,改为直接读取原始信号。错误信息:%s', recordA, ME_A.message); % 回退:读取原始完整信号 oldFolder = cd(dataFolder); [sigA_raw, FsA, ~] = rdsamp(recordA); cd(oldFolder); sigA = sigA_raw; % 不进行任何预处理 end fprintf('正在读取记录 %s ...\n', recordB); try [sigB, FsB] = readdata(recordB, dataFolder); catch ME_B warning('readdata 读取 %s 失败,改为直接读取原始信号。错误信息:%s', recordB, ME_B.message); oldFolder = cd(dataFolder); [sigB_raw, FsB, ~] = rdsamp(recordB); cd(oldFolder); sigB = sigB_raw; end % 检查采样率是否一致 if FsA ~= FsB error('两个记录的采样率不一致,无法直接比较。'); end Fs = FsA; % 让比较窗口对齐:取两者中较短的信号长度 minLen = min(size(sigA,1), size(sigB,1)); sigA = sigA(1:minLen, :); sigB = sigB(1:minLen, :); % 生成统一的时间轴(单位:秒) t = (0:minLen-1) / Fs; % 只显示前 10 秒的数据,便于观察细节 viewSec = 10; viewSamples = min(round(viewSec * Fs), minLen); tv = t(1:viewSamples); % ---- 可视化 ---- figure('Name', '信号对比:234 vs x_234', 'Position', [100, 100, 1200, 800]); % 1. 第一导联叠加对比 subplot(3,1,1); plot(tv, sigA(1:viewSamples, 1), 'b-', 'LineWidth', 1.2); hold on; plot(tv, sigB(1:viewSamples, 1), 'r--', 'LineWidth', 1.2); xlabel('时间 (秒)'); ylabel('幅值 (mV)'); title(sprintf('导联 1 前 %d 秒(蓝: 234, 红: x_234)', viewSec)); legend('234', 'x_234'); grid on; % 2. 第一导联差异信号 diff_lead1 = sigA(1:viewSamples, 1) - sigB(1:viewSamples, 1); subplot(3,1,2); plot(tv, diff_lead1, 'k-', 'LineWidth', 1); xlabel('时间 (秒)'); ylabel('差异 (mV)'); title('导联 1 差异 (234 - x_234)'); grid on; % 添加零线 hold on; plot([tv(1), tv(end)], [0 0], 'Color', [0.6 0.6 0.6]); % 3. 第二导联叠加对比 subplot(3,1,3); plot(tv, sigA(1:viewSamples, 2), 'b-', 'LineWidth', 1.2); hold on; plot(tv, sigB(1:viewSamples, 2), 'r--', 'LineWidth', 1.2); xlabel('时间 (秒)'); ylabel('幅值 (mV)'); title(sprintf('导联 2 前 %d 秒(蓝: 234, 红: x_234)', viewSec)); legend('234', 'x_234'); grid on; sgtitle(sprintf('记录 %s 与 %s 经过 readdata 处理后的信号对比', recordA, recordB)); ```  似乎没差别,我自己也看了其它信号并且放大范围,可以看出信号本身并无明显差异。 考虑到这里的问题主要是心律失常arrythmia,所以我们统计一下各个标签的数量: ```Matlab %% 总结各个文件中的注释标签类型及数量(基于 ASCII 字符映射) clear; clc; dataFolder = 'D:\ECG-Tran\mit-bih-arrhythmia-database'; recordNames = { '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', ... '111', '112', '113', '114', '115', '116', '117', '118', '119', ... '121', '122', '123', '124', ... '200', '201', '202', '203', '205', '207', '208', '209', '210', ... '212', '213', '214', '215', '217', '219', '220', '221', '222', '223', ... '228', '230', '231', '232', '233', '234' }; %% ========== 1. 构建映射表:字符 -> 描述 ========== % 心搏类型 (Beat annotations) beatMap = containers.Map(); beatMap('N') = '正常搏动'; beatMap('L') = '左束支传导阻滞搏动'; beatMap('R') = '右束支传导阻滞搏动'; beatMap('B') = '束支传导阻滞搏动(未指定)'; beatMap('A') = '房性早搏'; beatMap('a') = '异常房性早搏'; beatMap('J') = '交界性早搏'; beatMap('S') = '室上性早搏或异位搏动(房性或交界性)'; beatMap('V') = '室性早搏'; beatMap('r') = 'R-on-T 室性早搏'; beatMap('F') = '心室融合搏动(室性与正常融合)'; beatMap('e') = '房性逸搏'; beatMap('j') = '交界性逸搏'; beatMap('n') = '室上性逸搏(房性或交界性)'; beatMap('E') = '室性逸搏'; beatMap('/') = '起搏搏动'; beatMap('f') = '起搏与正常融合搏动'; beatMap('Q') = '不可分类搏动'; beatMap('?') = '学习期间未分类搏动'; % 非心搏注释 (Non-beat annotations) nonBeatMap = containers.Map(); nonBeatMap('[') = '室扑/室颤开始'; nonBeatMap('!') = '室扑波'; nonBeatMap(']') = '室扑/室颤结束'; nonBeatMap('x') = '未传导P波 (阻滞的房性早搏)'; nonBeatMap('(') = '波形开始'; nonBeatMap(')') = '波形结束'; nonBeatMap('p') = 'P波峰值'; nonBeatMap('t') = 'T波峰值'; nonBeatMap('u') = 'U波峰值'; nonBeatMap('`') = 'PQ 连接处'; nonBeatMap(',') = 'J点'; nonBeatMap('~') = '(未夺获)起搏器伪迹 或 信号质量变化'; % 有两种用途 nonBeatMap('|') = '孤立的 QRS 样伪迹'; nonBeatMap('+') = '节律变化'; nonBeatMap('s') = 'ST段变化'; nonBeatMap('T') = 'T波变化'; nonBeatMap('*') = '收缩期'; nonBeatMap('D') = '舒张期'; nonBeatMap('=') = '测量注释'; nonBeatMap('"') = '评论注释'; nonBeatMap('@') = '指向外部数据的链接'; % 合并总映射(优先使用 beatMap,若不存在再查 nonBeatMap) allMaps = containers.Map(); keys = [beatMap.keys, nonBeatMap.keys]; for i = 1:length(keys) key = keys{i}; if beatMap.isKey(key) allMaps(key) = beatMap(key); elseif nonBeatMap.isKey(key) allMaps(key) = nonBeatMap(key); end end %% ========== 2. 处理每个记录 ========== fprintf('%-8s | 标签类型及数量\n', '记录'); fprintf('%s\n', repmat('-', 100, 1)); for i = 1:length(recordNames) recName = recordNames{i}; oldFolder = cd(dataFolder); try [~, atype] = rdann(recName, 'atr'); % atype 为数值数组,每个数值是 ASCII 码 catch fprintf('%-8s | 无法读取注释\n', recName); cd(oldFolder); continue; end cd(oldFolder); if isempty(atype) fprintf('%-8s | 无注释\n', recName); continue; end % 将 ASCII 码转换为字符,组成字符串数组 chars = cellfun(@(x) char(x), num2cell(atype), 'UniformOutput', false); % 统计每个字符出现的次数 [uniqueChars, ~, idx] = unique(chars); counts = accumarray(idx, 1); % 生成输出字符串 infoParts = {}; for j = 1:length(uniqueChars) ch = uniqueChars{j}; count = counts(j); if allMaps.isKey(ch) desc = allMaps(ch); infoParts{end+1} = sprintf('''%s'' (%s): %d个', ch, desc, count); else % 未知字符:显示 ASCII 码和十六进制 asciiVal = double(ch); infoParts{end+1} = sprintf('''%s'' (0x%02X, 未知): %d个', ch, asciiVal, count); end end fprintf('%-8s | %s\n', recName, strjoin(infoParts, '; ')); end ``` ```Matlab 记录 | 标签类型及数量 ---------------------------------------------------------------------------------------------------- 100 | '+' (节律变化): 1个; 'A' (房性早搏): 33个; 'N' (正常搏动): 2239个; 'V' (室性早搏): 1个 101 | '+' (节律变化): 1个; 'A' (房性早搏): 3个; 'N' (正常搏动): 1860个; 'Q' (不可分类搏动): 2个; '|' (孤立的 QRS 样伪迹): 4个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 4个 102 | '+' (节律变化): 5个; '/' (起搏搏动): 2028个; 'N' (正常搏动): 99个; 'V' (室性早搏): 4个; 'f' (起搏与正常融合搏动): 56个 103 | '+' (节律变化): 1个; 'A' (房性早搏): 2个; 'N' (正常搏动): 2082个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 6个 104 | '+' (节律变化): 45个; '/' (起搏搏动): 1380个; 'N' (正常搏动): 163个; 'Q' (不可分类搏动): 18个; 'V' (室性早搏): 2个; 'f' (起搏与正常融合搏动): 666个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 37个 105 | '+' (节律变化): 1个; 'N' (正常搏动): 2526个; 'Q' (不可分类搏动): 5个; 'V' (室性早搏): 41个; '|' (孤立的 QRS 样伪迹): 30个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 88个 106 | '+' (节律变化): 41个; 'N' (正常搏动): 1507个; 'V' (室性早搏): 520个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 30个 107 | '+' (节律变化): 1个; '/' (起搏搏动): 2078个; 'V' (室性早搏): 59个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 2个 108 | '+' (节律变化): 1个; 'A' (房性早搏): 4个; 'F' (心室融合搏动(室性与正常融合)): 2个; 'N' (正常搏动): 1739个; 'V' (室性早搏): 17个; 'j' (交界性逸搏): 1个; 'x' (未传导P波 (阻滞的房性早搏)): 11个; '|' (孤立的 QRS 样伪迹): 8个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 41个 109 | '+' (节律变化): 1个; 'F' (心室融合搏动(室性与正常融合)): 2个; 'L' (左束支传导阻滞搏动): 2492个; 'V' (室性早搏): 38个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 2个 111 | '+' (节律变化): 1个; 'L' (左束支传导阻滞搏动): 2123个; 'V' (室性早搏): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 8个 112 | '+' (节律变化): 1个; 'A' (房性早搏): 2个; 'N' (正常搏动): 2537个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 10个 113 | '+' (节律变化): 1个; 'N' (正常搏动): 1789个; 'a' (异常房性早搏): 6个 114 | '+' (节律变化): 3个; 'A' (房性早搏): 10个; 'F' (心室融合搏动(室性与正常融合)): 4个; 'J' (交界性早搏): 2个; 'N' (正常搏动): 1820个; 'V' (室性早搏): 43个; '|' (孤立的 QRS 样伪迹): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 7个 115 | '+' (节律变化): 1个; 'N' (正常搏动): 1953个; '|' (孤立的 QRS 样伪迹): 6个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 2个 116 | '+' (节律变化): 1个; 'A' (房性早搏): 1个; 'N' (正常搏动): 2302个; 'V' (室性早搏): 109个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 8个 117 | '+' (节律变化): 1个; 'A' (房性早搏): 1个; 'N' (正常搏动): 1534个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 3个 118 | '+' (节律变化): 1个; 'A' (房性早搏): 96个; 'R' (右束支传导阻滞搏动): 2166个; 'V' (室性早搏): 16个; 'x' (未传导P波 (阻滞的房性早搏)): 10个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 12个 119 | '+' (节律变化): 103个; 'N' (正常搏动): 1543个; 'V' (室性早搏): 444个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 4个 121 | '+' (节律变化): 1个; 'A' (房性早搏): 1个; 'N' (正常搏动): 1861个; 'V' (室性早搏): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 12个 122 | '+' (节律变化): 1个; 'N' (正常搏动): 2476个; '|' (孤立的 QRS 样伪迹): 2个 123 | '+' (节律变化): 1个; 'N' (正常搏动): 1515个; 'V' (室性早搏): 3个 124 | '+' (节律变化): 13个; 'A' (房性早搏): 2个; 'F' (心室融合搏动(室性与正常融合)): 5个; 'J' (交界性早搏): 29个; 'R' (右束支传导阻滞搏动): 1531个; 'V' (室性早搏): 47个; 'j' (交界性逸搏): 5个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 2个 200 | '+' (节律变化): 148个; 'A' (房性早搏): 30个; 'F' (心室融合搏动(室性与正常融合)): 2个; 'N' (正常搏动): 1743个; 'V' (室性早搏): 826个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 43个 201 | '+' (节律变化): 35个; 'A' (房性早搏): 30个; 'F' (心室融合搏动(室性与正常融合)): 2个; 'J' (交界性早搏): 1个; 'N' (正常搏动): 1625个; 'V' (室性早搏): 198个; 'a' (异常房性早搏): 97个; 'j' (交界性逸搏): 10个; 'x' (未传导P波 (阻滞的房性早搏)): 37个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 4个 202 | '+' (节律变化): 8个; 'A' (房性早搏): 36个; 'F' (心室融合搏动(室性与正常融合)): 1个; 'N' (正常搏动): 2061个; 'V' (室性早搏): 19个; 'a' (异常房性早搏): 19个; '|' (孤立的 QRS 样伪迹): 2个 203 | '+' (节律变化): 45个; 'F' (心室融合搏动(室性与正常融合)): 1个; 'N' (正常搏动): 2529个; 'Q' (不可分类搏动): 4个; 'V' (室性早搏): 444个; 'a' (异常房性早搏): 2个; '|' (孤立的 QRS 样伪迹): 26个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 57个 205 | '+' (节律变化): 13个; 'A' (房性早搏): 3个; 'F' (心室融合搏动(室性与正常融合)): 11个; 'N' (正常搏动): 2571个; 'V' (室性早搏): 71个; '|' (孤立的 QRS 样伪迹): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 2个 207 | '!' (室扑波): 472个; '+' (节律变化): 24个; 'A' (房性早搏): 107个; 'E' (室性逸搏): 105个; 'L' (左束支传导阻滞搏动): 1457个; 'R' (右束支传导阻滞搏动): 86个; 'V' (室性早搏): 105个; '[' (室扑/室颤开始): 6个; ']' (室扑/室颤结束): 6个; '|' (孤立的 QRS 样伪迹): 2个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 15个 208 | '+' (节律变化): 53个; 'F' (心室融合搏动(室性与正常融合)): 373个; 'N' (正常搏动): 1586个; 'Q' (不可分类搏动): 2个; 'S' (室上性早搏或异位搏动(房性或交界性)): 2个; 'V' (室性早搏): 992个; '|' (孤立的 QRS 样伪迹): 8个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 24个 209 | '+' (节律变化): 21个; 'A' (房性早搏): 383个; 'N' (正常搏动): 2621个; 'V' (室性早搏): 1个; '|' (孤立的 QRS 样伪迹): 7个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 19个 210 | '+' (节律变化): 17个; 'E' (室性逸搏): 1个; 'F' (心室融合搏动(室性与正常融合)): 10个; 'N' (正常搏动): 2423个; 'V' (室性早搏): 194个; 'a' (异常房性早搏): 22个; '|' (孤立的 QRS 样伪迹): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 17个 212 | '+' (节律变化): 1个; 'N' (正常搏动): 923个; 'R' (右束支传导阻滞搏动): 1825个; '|' (孤立的 QRS 样伪迹): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 13个 213 | '+' (节律变化): 43个; 'A' (房性早搏): 25个; 'F' (心室融合搏动(室性与正常融合)): 362个; 'N' (正常搏动): 2641个; 'V' (室性早搏): 220个; 'a' (异常房性早搏): 3个 214 | '"' (评论注释): 1个; '+' (节律变化): 25个; 'F' (心室融合搏动(室性与正常融合)): 1个; 'L' (左束支传导阻滞搏动): 2003个; 'Q' (不可分类搏动): 2个; 'V' (室性早搏): 256个; '|' (孤立的 QRS 样伪迹): 5个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 4个 215 | '"' (评论注释): 2个; '+' (节律变化): 5个; 'A' (房性早搏): 3个; 'F' (心室融合搏动(室性与正常融合)): 1个; 'N' (正常搏动): 3195个; 'V' (室性早搏): 164个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 30个 217 | '+' (节律变化): 67个; '/' (起搏搏动): 1542个; 'N' (正常搏动): 244个; 'V' (室性早搏): 162个; 'f' (起搏与正常融合搏动): 260个; '|' (孤立的 QRS 样伪迹): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 4个 219 | '"' (评论注释): 4个; '+' (节律变化): 21个; 'A' (房性早搏): 7个; 'F' (心室融合搏动(室性与正常融合)): 1个; 'N' (正常搏动): 2082个; 'V' (室性早搏): 64个; 'x' (未传导P波 (阻滞的房性早搏)): 133个 220 | '+' (节律变化): 16个; 'A' (房性早搏): 94个; 'N' (正常搏动): 1954个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 4个 221 | '+' (节律变化): 23个; 'N' (正常搏动): 2031个; 'V' (室性早搏): 396个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 12个 222 | '+' (节律变化): 136个; 'A' (房性早搏): 208个; 'J' (交界性早搏): 1个; 'N' (正常搏动): 2062个; 'j' (交界性逸搏): 212个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 15个 223 | '+' (节律变化): 28个; 'A' (房性早搏): 72个; 'F' (心室融合搏动(室性与正常融合)): 14个; 'N' (正常搏动): 2029个; 'V' (室性早搏): 473个; 'a' (异常房性早搏): 1个; 'e' (房性逸搏): 16个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 10个 228 | '"' (评论注释): 3个; '+' (节律变化): 41个; 'A' (房性早搏): 3个; 'N' (正常搏动): 1688个; 'V' (室性早搏): 362个; '|' (孤立的 QRS 样伪迹): 24个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 20个 230 | '+' (节律变化): 207个; 'N' (正常搏动): 2255个; 'V' (室性早搏): 1个; '|' (孤立的 QRS 样伪迹): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 2个 231 | '"' (评论注释): 427个; '+' (节律变化): 11个; 'A' (房性早搏): 1个; 'N' (正常搏动): 314个; 'R' (右束支传导阻滞搏动): 1254个; 'V' (室性早搏): 2个; 'x' (未传导P波 (阻滞的房性早搏)): 2个 232 | '+' (节律变化): 1个; 'A' (房性早搏): 1382个; 'R' (右束支传导阻滞搏动): 397个; 'j' (交界性逸搏): 1个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 35个 233 | '+' (节律变化): 71个; 'A' (房性早搏): 7个; 'F' (心室融合搏动(室性与正常融合)): 11个; 'N' (正常搏动): 2230个; 'V' (室性早搏): 831个; '|' (孤立的 QRS 样伪迹): 2个 234 | '+' (节律变化): 3个; 'J' (交界性早搏): 50个; 'N' (正常搏动): 2700个; 'V' (室性早搏): 3个; '~' ((未夺获)起搏器伪迹 或 信号质量变化): 8个 ``` 读取数据与降采样,该数据库是360Hz,为了配合我们之前的数据,我们可以选择将其降采样(需要将注释同步考虑): ```Matlab function [sig, Fs, tm, annot_pos, annot_sym] = readdata(recordName, dataFolder, targetFs) % 读取心电图信号,从第5秒开始裁切,进行去趋势和带通滤波,并降采样至目标频率 % 同时读取 .atr 注释,并将注释位置同步映射到降采样后的时间轴上 % 输入: % recordName - 记录名称 % dataFolder - 数据文件夹路径 % targetFs - 目标采样率 (Hz),默认 128 % 输出: % sig - 处理后的双导联信号 [nSamples × 2] % Fs - 目标采样率 (Hz) % tm - 时间向量(从0开始,对应降采样后的信号) % annot_pos - 降采样后的注释样本索引 (列向量,与 annot_sym 对应) % annot_sym - 注释符号的 cell 数组 (如 {'N','V','A',...}) if nargin < 3 targetFs = 128; % 默认目标采样率 128 Hz end oldFolder = cd(dataFolder); cleanup = onCleanup(@() cd(oldFolder)); % ------------------ 读取信号 ------------------ [sig_full, origFs] = rdsamp(recordName); if isempty(sig_full) error('无法读取记录 %s 的信号', recordName); end % 第5秒对应的原始样本起始索引 (1-based) start_second = 5; startSample = round(start_second * origFs) + 1; if startSample > size(sig_full, 1) error('第%d秒(样本 %d)超出信号长度(%d)', start_second, startSample, size(sig_full,1)); end % 裁切信号 sig_cropped = sig_full(startSample:end, :); fprintf('记录 %s:从第%d秒(样本 %d)开始裁切,剩余 %d 个样本\n', ... recordName, start_second, startSample, size(sig_cropped,1)); % 去趋势 + 带通滤波 (0.5-40 Hz) sig_filtered = zeros(size(sig_cropped)); nyquist = origFs / 2; [b, a] = butter(4, [0.5/nyquist, 40/nyquist], 'bandpass'); for lead = 1:2 signal_detrend = detrend(sig_cropped(:, lead)); sig_filtered(:, lead) = filtfilt(b, a, signal_detrend); end % 降采样至目标采样率 if origFs ~= targetFs [p, q] = rat(targetFs / origFs, 1e-12); fprintf('重采样:从 %.1f Hz 到 %.1f Hz (因子 %.6f)\n', origFs, targetFs, p/q); n_out = ceil(size(sig_filtered, 1) * p / q); sig = zeros(n_out, 2); for lead = 1:2 sig(:, lead) = resample(sig_filtered(:, lead), p, q); end Fs = targetFs; else sig = sig_filtered; Fs = origFs; end % 时间向量 (秒,从0开始) tm = (0:size(sig,1)-1) / Fs; % ------------------ 读取并同步注释 ------------------ annot_pos = []; annot_sym = {}; try % 读取 atr 注释:ann_orig 为样本位置(0-based),anntype_orig 为 ASCII 码数值 [ann_orig, anntype_orig] = rdann(recordName, 'atr'); if isempty(ann_orig) fprintf('记录 %s 无注释数据\n', recordName); return; end % 转换为 1-based 索引,并转换 ASCII 码为字符 orig_idx = ann_orig + 1; % 转为 1-based sym_cell = cellfun(@(x) char(x), num2cell(anntype_orig), 'UniformOutput', false); % 只保留裁切起始点之后的注释 keep = (orig_idx >= startSample); orig_idx = orig_idx(keep); sym_cell = sym_cell(keep); if isempty(orig_idx) fprintf('记录 %s 在第5秒后无注释\n', recordName); return; end % 计算裁切后的相对样本索引 (基于原始采样率) cropped_idx = orig_idx - startSample + 1; % 1-based,相对于 sig_cropped % 裁切后的时间 (秒) t_cropped = (cropped_idx - 1) / origFs; % 映射到降采样后的样本索引 (四舍五入) new_idx = round(t_cropped * targetFs) + 1; % 剔除越界的索引 valid = (new_idx >= 1) & (new_idx <= size(sig,1)); annot_pos = new_idx(valid); annot_sym = sym_cell(valid); % 可选:去除重复位置上的多余注释(保留第一个) [annot_pos, unique_ia] = unique(annot_pos, 'stable'); annot_sym = annot_sym(unique_ia); fprintf('成功同步 %d 个注释到降采样信号 (总注释 %d)\n', length(annot_pos), sum(keep)); catch ME warning('读取或同步注释时出错: %s', ME.message); end end ```  各种标签中表示R峰位置的有: ```Matlab beat_chars = {'N','L','R','B','A','a','J','S','V','r','F','e','j','n','E','/','f','Q','?'}; ``` 我在这里写一个输出R峰索引的脚本: ```Matlab function [r_idx, r_times] = get_r_peaks(annot_pos, annot_sym, Fs) % GET_R_PEAKS 从注释中筛选出指定心搏类型的R波位置 % 输入: % annot_pos - 降采样后的注释样本索引 (列向量) % annot_sym - 注释符号的 cell 数组 (与 annot_pos 对应) % Fs - 当前信号的采样率 (Hz) % 输出: % r_idx - 筛选后的R波样本索引 (列向量) % r_times - 对应的时刻 (秒,列向量) % 定义需要保留的心搏类型 beat_chars = {'N','L','R','B','A','a','J','S','V','r','F','e','j','n','E','/','f','Q','?'}; % 检查输入是否为空 if isempty(annot_pos) || isempty(annot_sym) r_idx = []; r_times = []; fprintf('警告:没有提供任何注释,无法提取R波。\n'); return; end % 确保 annot_pos 是列向量 annot_pos = annot_pos(:); % 确保 annot_sym 是列 cell 数组 if isrow(annot_sym) annot_sym = annot_sym'; end % 创建逻辑掩码:每个符号是否属于目标心搏类型 keep_mask = ismember(annot_sym, beat_chars); % 筛选出R波对应的样本索引 r_idx = annot_pos(keep_mask); % 计算对应的时间 (秒) tm = (idx-1)/Fs r_times = (r_idx - 1) / Fs; end ``` **\*\*\*\*\*\*\*\*\*\*END\*\*\*\*\*\*\*\*\*\***
相关推荐
有味道的男人2 小时前
AI 效率翻倍:对接 1688 拍立淘接口,商品全量信息一键抓取m0_741173332 小时前
如何处理SQL中的NULL值_使用ISNULL或COALESCE函数志栋智能2 小时前
超自动化巡检:解锁运维数据的深层价值m0_380113842 小时前
补单系统搭建及源码分享步辞3 小时前
css伪类选择器-nth-child应用技巧_循环选择列表或表格行的实现方法阿丰资源3 小时前
基于SpringBoot+MySQL的社区团购系统设计与实现(附源码+文档+数据库,直接运行)2301_803875614 小时前
Python怎么计算NumPy数组的切比雪夫距离_使用abs与max求解还是阿落呀4 小时前
第二章 数据类型、表的约束希望永不加班4 小时前
SpringBoot 数据库索引优化:慢查询分析