EDA365电子论坛网

标题: MATLAB中cell数组的是是非非 [打印本页]

作者: thinkfunny    时间: 2020-12-28 17:43
标题: MATLAB中cell数组的是是非非

% a' K( b  ]! V: _$ R由于工作需要,经常要处理大量的实验数据.基本都是由仪器导出来,随着社会发展的进步,人们获取数据的量在不断增长,很多人都是,现在已经是海量数据时代了...
% z9 q$ G- I; Q7 [" D$ p从cell使用说起 ! f% S1 E+ k* i2 P
在读取文件的时候,cell数组(各种翻译都有,元胞数组,单元数组...直接无视)是MATLAB的宠儿,基本都会出现,长期使用发现频率比struct高了不少~无论是Import Data还是使用textscan之类来获取数据.从长期使用高级语言的角度来说,特别是习惯了面向对象之后i,更习惯使用struct数组,概念也很相似,奈何现实是...我们先看一下Matlab在help给出的定义:" |9 `/ m" l2 _5 T: ^7 ]
A cell array is a collection of containers called cells in which you can store different types of data.
, J8 ]! G9 P+ p! f
0 a2 q7 [4 t! V6 F. r% E1 f7 Q( C精华之处就是在可以存储不同类型的数据.可以是Matlab的类型或者自定义的类型.
' ]/ V# H/ g  k4 [. j6 _7 v7 N$ @9 ucell数组的一些操作
+ ]) \7 c' k% ]8 F创建:直接使用{}以及cell(...)形式,另外 下标法赋值也可以.注意后两种可以预配内存,内存是空间连续的~0 U0 ~/ }* |" M9 p' k( W- g
读取内容:{下标}和(下标)  区别在于类型()是cell数组 ,{}是实际类型.结果显示是一致的
* I: w! V) k* R# ?>> a={'啊',123,[3 5 6],[1 2;7 8],sym(1)}; O' J: o1 [5 _+ P: S
a = 0 J+ p" W8 Z: d" F: |0 @" F
    '啊'    [123]    [1x3 double]    [2x2 double]    [1x1 sym]# M* d0 y" P" p+ o% F$ N. {
>> class(a{1})7 k: Z. |% V  v( o! l
ans =
8 z+ E2 o- ]' v0 |  L9 Dchar6 O  |- E9 f- z
>> class(a(1))
$ Y3 D: Q% w4 K* H2 V: rans =
2 w: s0 e: X) Q7 O; kcell- a3 r( g7 ?" `: f* U
>> 9 m- H. B2 i/ S1 v5 ^, I2 T+ P0 M
C{5,3}{4,7}(:,4)1 n$ \7 j1 O+ B' I' Q
解读: cell数组的一个元素为cell类型,包含一个普通矩阵类型
* {8 }" h7 ~- U! Ex = C{5,3};      % x is a cell array
; [! k1 v1 {/ u1 r" E( x4 qy = x{4,7};      % y is also a cell array
  G7 O( A! q* B6 Yz = y(:,4)       % z is a standard array
" ^, G' M0 _, w- M, N复制代码
7 u  y" a& h: L8 p: r; _  l调整内容:添加和删除与普通矩阵方法一致: F2 ?% E( A! ]& B5 C
相关函数:
: y8 u8 _0 U% S1 `0 }  celldisp:显示所有的内容
5 D  a2 i* V" u7 r: s$ S1 A9 lcell:创建空的元胞数组8 Q5 W9 e9 t/ E9 n
  cellplot:利用图形方式显示内容! N& q- n5 E" x+ r4 O9 g5 L, N0 v
  cell2mat:将数组转变成为普通的矩阵
* b0 R) v8 F9 c2 |9 l. ~& l: m: G7 v  mat2cell:将数值矩阵转变成为cell数组
6 {* R, X" h. e0 v  num2cell:将数值数组转变成为cell数组' n/ d8 p6 J% j! R' u+ l
  cell2struct:将数组转变成为结构
3 z0 C  O! D7 m& b0 }2 s  struct2cell:将结构转变为cell数组
3 \5 q# @" L5 \  iscell:判断输入是否为cell数组
' ?% {, |/ G  E# R$ y1 }1 xcellfun:为cell数组的每个cell执行指定的函数 fun可以是特殊函数或者句柄
! E& X+ J9 U: D5 idays{1} = 'Sunday';    days{2} = 'Monday';
) J4 V& {' I. m! S* p4 fdays{3} = 'Tuesday';   days{4} = 'Wednesday';
- }7 M7 d# J' }; pdays{5} = 'Thursday';  days{6} = 'Friday';
8 x8 P0 O8 M% h" hdays{7} = 'Saturday';. B: C: r( p+ b# V6 B6 e; M! J

8 x5 l2 Q/ t7 T% r5 A$ _6 KshortNames = cellfun(@(x)x(1:3), days, 'UniformOutput', false)
' i; Q, w8 }+ W9 J3 M& }: ZshortNames =
; I# k( w6 b" q, D; Q' d! w    'Sun'    'Mon'    'Tue'    'Wed'    'Thu'    'Fri'    'Sat'
) e2 Y" X0 T+ N" u6 C& c. U9 q复制代码
  R4 R+ t7 b1 d  deal:将输入参数赋值给输出 [Y1, Y2, Y3, ...] = deal(X{:}) ->可以简化[a,b,c,d] = C{:}5 ^. t2 u, h) J. O; d" Q
cell数组的类型转换看到上面的那些类型转换函数,也许你会笑了,感觉也没有什么特别的,但是使用过这个cell数组的朋友,估计大部分都会有转换失败的经历-_-很坑爹的...5 A! C, V* G, d  p% Z; `

1 K- i* t) a+ r# YCell Array and Struct Array8 J1 C) n% p+ p; m5 ]
s = cell2struct(c, fields, dim) cell数组转换为struct数组,注意fields为char数组或者cell数组,而且size(c,dim) == length(fields)   % If fields is a cell arraysize(c,dim) == size(fields,1)   % If fields is a char array  这个经常错误就是fields类型以及dim不对- e! A1 v, [3 w/ Z
   c = struct2cell(s)  struct数组转换为cell数组 这个基本没有什么错误的/ G" r  `1 k; O- Y

/ t6 ^+ z# ^" ^0 c) K7 BMatrix and Cell Array- m, {8 Q' Z" A, E
c = mat2cell(x, m, n) 转换为 m行n列cell数组 m = cell2mat(c) 必须是同一类型,而且限制不可包含cell数组或object类型,但是struct结构是可以的(同样这个struct不含 cell和object类型,否则依旧出错)
- c$ u1 G2 w: E2 T
7 H4 B. ^  ?* {) I% e- }Double and Cell Array
7 P5 h+ Y3 Q) Q0 |2 j  I# DC = num2cell(A, [dim1, dim2, ...]) 返回C的维数是numel(A)/prod(X,Y,...)   dimN 是一个整数,范围是1到ndims(A)8 |1 L8 T4 y0 U
只有数值矩阵才可以直接转换为cell,没有供cell转为double的方法.这是非常让人恼火的!不过理解之后就知道,cell本来就是混合类型的,直接转向数值类型单一矩阵,这样是不合理的.通常如果是的确是数值类型的可以走以下路线:cell->cell2mat 这时候注意cell2mat的条件非cell和object.否则,循环或者cellfun处理.如果可以使用 cell2mat 或者cat(dim,c{:}).很多时候都很方便
: D( B4 |$ e$ Y/ z* jCell Arrays of Strings * j, e& }- v/ ]
单独列出了是因为很多时候都要接触这个,基本txt之类读取来的数值数据都是char的cell数组~
' u: ~0 f$ S- @$ S, p可以使用cell参数与字符有关的部分函数(基本都支持)  w) P% a  ^$ B( r% r
cellstr      Convert a character array to a cell array of strings.会去除末尾空白2 v) }; D% t' n* L1 f$ y) S
char        Convert a cell array of strings to a character array. 会恢复转换时候失去的空白: p$ _6 n" n  `1 S5 O: v
deblank   Remove trailing blanks from a string.
& P4 g# [: O* ?iscellstr    Return true for acell array of strings.
; y9 z( S4 Z2 F$ C/ J3 _; [sort        排序.
  _2 L/ _1 e, L  ystrcat连接字符./ Z7 T) U  M" G9 \. l1 v: g% d
strcmp对比字符.8 C9 i$ K" N$ L( e. t* y7 V& P
strmatch 查找字符.
; r8 ^. x; g) r, O  Z* F" `2 ~" cstrrep 替换字符
' C/ p# A3 a& `* m; S9 Cregexp系列及accumarray支持行列向量.
2 h4 k6 y% j! X+ E5 k6 I
; X+ z$ V5 X( g4 N# H2 i+ t读写
' _5 s0 T, N, M' \数据读取进来了,处理后当然是需要保存的,可是面对要求 你总是很无奈,要是可以.mat格式那个很好啊 可是大部分要求都是txt之类的.(不明白为什么呢 其实数据库之类Matlab也是支持的...唉,需求总是最后的注脚...)首先要了解怎么情况会有cell数组产生:具体查看textscan 的说明.大文件的读取首先推荐这个函数,处理灵活可以省去很多功夫,具体的格式设置很关键!能够有效分离cell数据的结果方便处理~否则3000万个数据循环绝对是out of memory...尽量使用高级的IO读写...另外,7.0很多读取都是数值返回cell的char类型数组 7.6以上都使用double了,包括xlsread...* H; K! A3 J% B0 [! e
如果允许,xlswrite是最好的选择~大量数据测试的结果还是非常好的1 n$ @, v& Z, {1 ?2 n1 F: {8 d; J
在Matlab帮助里面的循环例子:
! W% L. a" u4 y2 f  H; X5 pmycell = { 'a' 1 2 3 ; 'b' 4 5 6 };, Y* B& a" Z# U& e
[nrows,ncols]= size(mycell);
2 z4 P" y, O8 o& k0 @- f6 ?( i6 qfilename = 'celldata.dat';
- u, N: F7 L! {fid = fopen(filename, 'w');4 N3 J' ~* t5 \5 U- ^) v$ l4 n
for row=1:nrows
) |- f% s& ~9 S1 l    fprintf(fid, '%s %d %d %d\n', mycell{row,:});; v9 W+ ^5 ?% _9 v
end
0 a3 r# L! G/ q9 g& `fclose(fid);
- e' C' ]4 G$ V, P' g0 F) y4 p' j% p7 O/ l
复制代码
1 B  m+ `. j9 l仅有数值时候 可以考虑先cell2mat 然后csvwrite.) [- G5 {8 Q. y$ Q

2 t1 @/ y3 l( O' `# T/ a+ q+ o# l, v# _0 V
总结
! Z' f6 B0 l; ?; c基本是就是总结了一下用法,特别是转换和保存方面的,相对于struct数组,由于Matlab中支持甚多,因此也就常用了.功能偏弱,但是基本按照规则,还是可以尽量减少出错的.
. }  R% Q* `+ q3 q6 q) z* n3 L希望大家也交换一下使用的心得~
作者: CCxiaom    时间: 2020-12-28 19:07
MATLAB中cell数组的是是非非




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2