|  | 
 
| 
本帖最后由 uqHZau 于 2020-12-16 10:14 编辑 4 e( |- o: p) o% ]/ a: c8 q9 i
x
EDA365欢迎您登录!您需要 登录 才可以下载或查看,没有帐号?注册  " {$ H; x: N7 }
 目录:
 表之间的操作熟悉SQL语言的读者对连接的概念应该不会陌生,连接就是把两个或者多个表按照一定的逻辑组合起来。MATLAB的table对象也支持表之间的连接运算,包括内连接,左右连接,全连接。为了节省篇幅,这节略去table对象的构造过程,直接介绍各种连接函数和连接的结果。(本节Employee和Department的例子参考了维基SQL条目)下例表Table.1和Table.2是要使用的原始数据:Table.1 Employee表A- k/ t% Q4 F8 f4 G% E表之间的操作table的属性和支持的操作; n5 K! [/ c& h7 g
 
 | Employee | DepartmentID |  | Rafferty | 31 |  | Jones | 33 |  | Steinberg | 33 |  | Robinson | 34 |  | Smith | 34 |  | Jasper | 35 | 
 ; J7 Q1 Z' p6 z4 JTable.2 Employee表B! W, G4 M' g) M- ^
 % {5 {* {5 R# R% A) m3 y. p* U
 
 | DepartmentID | DepartmentName |  | 31 | Sales |  | 32 | Foundation |  | 33 | Engineering |  | 34 | HR |  | 35 | Marketing | 
 ! T8 o6 z9 L  _/ P$ h! t& Z7 t' Q8 z9 l" O& o* O. t
 
 * ~$ v/ e3 F3 L, T( f; i, Z& S( Y# h2 J# q- c  y
 
 8 ?7 D" V0 j2 b. c. R
 # N+ V2 Y1 Y  @  Z1 `: V3 A; K1 z! L. @: Z9 u
 
 3 G& k$ e  j+ j4 e+ h% K# q7 I$ h2 a/ k8 ~! i/ z& y7 _
 3 I" x" z3 Q. v5 |+ l- E" b
 
 7 q9 o1 L# i0 Y: E5 i' z
 " m$ _+ n3 D( k' F4 R- u
 $ p7 m5 u5 A! m* P; h7 R# zTable.1中有员工的LastName和所在部门的号码,而表Table.2中有部门号码对应的名字,如果我们想知道每个员工所在部门的名字,要查两次表:首先从表Table.1得到某员工所在部门的号码,再通过这个号码去到表Table.2中去找到对应的名字,这样做不是很方便。 如果能把表Table.2和表Table.2中的DepartmentID“对上”,从而构造出一个有三列数据的新表,并且其中三列分别是LastName,DepartmentID,DepartmentName,那么就只用查一次表了,这个操作其实就是table的join操作。
 其中join函数的第一个参数叫做左表,第二个参数叫做右表。 t1用表格形式表示如Table.3所示,请读者自行核对。为了说明左连接,右连接和全连接,我们把表Table.1稍作修改,把最后一行Jasper的DepartmentID改成36,如表Table.4Table.3 join(A,B)% join>> t1 = join(A,B)       % join的第一个参数叫做左表,第二个参数叫做右表t1 =     LastName      DepartmentID    DepartmentName    ___________    ____________    ______________    'Rafferty'     31              'Sales'    'Jones'        33              'Engineering'    'Steinberg'    33              'Engineering'    'Robinson'     34              'HR'    'Smith'        34              'HR'    'Jasper'       35              'Marketing'. C7 J; k3 z+ N. }% y
 6 x: A! c# f7 s' O4 X
 | Employee | DepartmentID | DepartmentName |  | Rafferty | 31 | Sales |  | Jones | 33 | Engineering |  | Steinberg | 33 | Engineering |  | Robinson | 34 | HR |  | Smith | 34 | HR |  | Jasper | 35 | Marketing | 
 4 f4 b! E( _/ [- a, g0 UTable.4 Employee表C5 }  I& A) O. g8 e( _
 
 | Employee | DepartmentID |  | Rafferty | 31 |  | Jones | 33 |  | Steinberg | 33 |  | Robinson | 34 |  | Smith | 34 |  | Jasper | 36 | 
 & I/ x4 f1 d9 x! x- z, L
 * t8 W6 a' ]  Z* A, q5 d$ l# x6 Q1 ]" H! ~) @) d6 @8 r
 ( H/ ^: B5 c" v6 K+ l
 
 ) R/ j9 W! \1 Z4 N3 h1 y5 L
 - u" W7 d% D1 m4 [, D5 `1 E$ v7 Q, @5 l7 V
 ) }) C  [3 S! ], v0 f, `3 y5 M$ e
 
 6 F# H/ g1 q/ N" G0 T8 ]: z/ N3 _6 x' ~; h9 R+ X4 S
 ) A5 L: n& N* ?/ x  h7 y
 
 2 i/ \7 P' A) z0 N" c$ D! p+ H2 o& I0 @7 [) P: A. \4 D
 所谓左连接,即连接结果表中将包含"左表"的所有记录, 即使那些记录在"右表" 没有符合连接条件的匹配。
 观察t3的结果,其中左表Table.4 中Jasper的DepartmentID是36,在表 Table.2中没有任何对应的行,但是左连接的结果t3中仍然保存了Japser项,并且其对应的DepartmentName为默认空字串。 所谓右外连接, 与左外连接完全类似, 只不过是作连接的表的顺序相反而已. 如果“左表”右连接“右表”, 那么"右表" 中的每一行在连接表中至少会出现一次. 如果 “右表”的记录在"左表"中未找到匹配行, 连接表中来源于“左表”的列的值设为默认空值。右表Table.2中的DepartmentID 35和36在表Table.4都没有任何员工与之对应,但是右连接的结果t4保留了这些没有员工对应的Department。% 左连接>> t3 = outerjoin(C,B,'Type','left','MergeKeys',true)t3 =    LastName      DepartmentID    DepartmentName    ___________    ____________    ______________    'Rafferty'     31              'Sales'    'Jones'        33              'Engineering'    'Steinberg'    33              'Engineering'    'Robinson'     34              'HR'    'Smith'        34              'HR'    'Jasper'       36              ''           %<-----2 l; o! H; c8 A/ }8 H9 i
 全连接是左右外连接的并集. 连接表包含被连接的表的所有记录, 如果缺少匹配的记录, 即以默认值填充。这允许我们查看每一个在部门里的员工和每一个拥有雇员的部门, 同时, 还能看到不在任何部门的员工以及没有任何员工的部门% 右连接>> t4 = outerjoin(C,B,'Type','right','MergeKeys',true)t4 =   LastName      DepartmentID    DepartmentName    ___________    ____________    ______________    'Rafferty'     31              'Sales'    ''             32              'Foundation'    %<-----    'Jones'        33              'Engineering'    'Steinberg'    33              'Engineering'    'Robinson'     34              'HR'    'Smith'        34              'HR'    ''             35              'Marketing'     %<-----9 k9 t4 h6 v; M5 z
 内连接(inner join)是应用程序中用的普遍的"连接"操作,它一般都是默认连接类型。内连接基于连接谓词,即DepartmentID,将两张表的列组合在一起,产生新的结果表。查询会将 A 表的每一行和 B 表的每一行进行比较,并找出满足连接谓词的组合% 全连接t5 = outerjoin(C,B,'MergeKeys',true)t5 =    LastName      DepartmentID    DepartmentName    ___________    ____________    ______________    'Rafferty'     31              'Sales'    ''             32              'Foundation'   %<-----    'Jones'        33              'Engineering'    'Steinberg'    33              'Engineering'    'Robinson'     34              'HR'    'Smith'        34              'HR'    ''             35              'Marketing'    %<-----    'Jasper'       36              ''             %<-----1 G, Z; ^8 e( {/ i
 t1和t5的结果类似,join和innerjoin的区别在于join对两个表的契合度要求更高,表1中的Key一定要在表2中也出现,如果尝试连接表3和表2,因为表C的Jasper的DepartmentID变成了36,而36在表2中不存在,MATLAB报错如下:% 内连接>> t5 = innerjoin(C,B)t5 =    LastName      DepartmentID    DepartmentName    ___________    ____________    ______________    'Rafferty'     31              'Sales'    'Jones'        33              'Engineering'    'Steinberg'    33              'Engineering'    'Robinson'     34              'HR'    'Smith'        34              'HR'0 u! X/ B" c8 G4 m8 f# O3 N
 - g+ J) a' A) R& `7 M3 o: b* O% join报错>> join(C,B)Error using table/join (line 130)The key variable for B must contain all values in the key variable for A.>> [a b] = lasterra =Error using table/join (line 130)The key variable for B must contain all values in the key variable for A.b =MATLAB:table:join: LeftKeyValueNotFound& g; j4 d3 g3 O" i; `* [
 5 `' {5 K6 ~/ F
 table的属性和支持的操作
 9 |/ g8 V1 P! f4 }2 C# q7 n  T" D) N; v+ x' b6 {
 最后做个总结,table是MATLAB从R2013b开始新引入的一个类(数据类型)。用UML(Unified Modeling Language)中的类图,可以表示如图 Figure.1Figure.1 table的Class Diagram! S" D1 W" ]9 w9 l4 _
 7 `/ P( y6 W4 J1 v
 
  + ]4 W8 \, Q3 u! R- e+ F% k 
 ( J! ~- S' ~6 i! f( X. G3 B图Figure.1中的属性除Properties外都是私有属性,即不可以用dot语法直接访问
 按照错误信息的提示,我们可以通过Properties这个metadata来访问这些属性,表\ref{map_phone_book_table}对应的table中的Properties将返回如下的内容% 通过Properties这个中间属性来访问table的其它属性>> t1.VariableNamesYou can not access the 'VariableNames' property directly.  Access it using dot subscripting via .Properties.VariableNames.9 }9 F9 C: v1 `9 L& c% m
 图Figure.1中的中Import and export,Size and Shape, set, Data Organization操作代表一些列可以施加在table上的方法的集合。我们可以通过help命令来得到该类的帮助信息:% Properties作为访问table其它属性的中间层>> t1.Propertiesans =             Description: ''    VariableDescriptions: {}           VariableUnits: {}          DimensionNames: {'Row'  'Variable'}                UserData: []                RowNames: {}           VariableNames: {'Name'  'Number'}>> t1.Properties.VariableNamesans =    'Name'    'Number'& S. r9 ^: {4 k" t' p
 其中有这些方法的介绍,这里大致罗列如下,方便读者查阅。>> help table' p8 N" T8 k% B7 C
 Import and export类的操作: ^9 F& g9 g% O/ a! ^1 b8 k* U
 eadtable 读入一个文件,创建table对象writetable 普通函数,把table写入一个文件,内部调用writewrite 类方法,把table写入一个文件' O5 q; v  t) z) s- D6 k; r
Size and shape类的操作3 o3 L7 s) k7 U, Z* D" _
 istable 判断一个变量是否是table类型size 返回table的高和宽,表头不计width 返回table的宽height 返回table的高ndims 返回table的维度numel 返回table高和宽的乘积horcat 横向串接tablevercat 纵向串接table% Q; R7 y, U  S/ n
Set membership类的操作% R. l' E% `1 y' X" k' D1 A3 I
 intersect 返回两表中的相同的行ismember 查询表中的行是否在另一表中也出现setdiff 查询两表之间的差异unique 返回的表中没有相同的行sextor 两个集合交集的非union 两个集合的并join 自然连接innterjoin 内连接outerjoin 外连接! G1 p5 a8 X( o! t8 J; k7 B
Data organization的操作  O/ k" B$ l" c5 E! S
 summary 返回table的基本信息sortrows 给table按照制定的row排序stack 把table的各列摞成一列unstack 把table的某一列展开成为若干列ismissing 找到table中那些没有赋值的项,返回logical indexstandizeMissing 给未赋值项赋默认值' D5 A' V4 k6 ^# J, L( D
vaRFun 把函数作用在table中选定的变量上rowfun 把函数作用在table的每列上0 |2 @" p/ S' ?+ u- x
 ! W) \; [9 v& n0 y/ @
 ! A- Q6 F, X( x6 X& }
 | 
 |