|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 uqHZau 于 2020-12-16 10:14 编辑
- w$ ]! S1 \% R, a0 o- ]
% @8 g- J. z- n3 ?- ^目录:- 表之间的操作
- table的属性和支持的操作8 c- V V8 ~ ^$ P. H4 H; f, e
表之间的操作熟悉SQL语言的读者对连接的概念应该不会陌生,连接就是把两个或者多个表按照一定的逻辑组合起来。MATLAB的table对象也支持表之间的连接运算,包括内连接,左右连接,全连接。为了节省篇幅,这节略去table对象的构造过程,直接介绍各种连接函数和连接的结果。(本节Employee和Department的例子参考了维基SQL条目)下例表Table.1和Table.2是要使用的原始数据:Table.1 Employee表A" g6 S, q. k( N; T
Employee | DepartmentID | Rafferty | 31 | Jones | 33 | Steinberg | 33 | Robinson | 34 | Smith | 34 | Jasper | 35 |
: X: u& Z7 O& k# ]6 P! hTable.2 Employee表B0 `8 [6 S- _. @
* s; c6 `* G# H/ IDepartmentID | DepartmentName | 31 | Sales | 32 | Foundation | 33 | Engineering | 34 | HR | 35 | Marketing |
7 {# X( o$ S0 Y. F$ ]! W2 y
0 x; a3 k% |7 H4 w: R. d6 W. M" }$ Y* J
* {' k. P; P, Q
2 I+ J7 |1 a* z/ h
( ?: h5 \- g; J2 a4 _1 t R0 |' x4 T3 C% b& i# E+ U/ C
* \3 F+ C+ H5 C
s7 g% p# r) ~( g' @" W# A( V$ {, ~% f
|5 t. N. x2 E, r
. I y0 {+ G% j x
8 e* t) O1 d ~* yTable.1中有员工的LastName和所在部门的号码,而表Table.2中有部门号码对应的名字,如果我们想知道每个员工所在部门的名字,要查两次表:首先从表Table.1得到某员工所在部门的号码,再通过这个号码去到表Table.2中去找到对应的名字,这样做不是很方便。 如果能把表Table.2和表Table.2中的DepartmentID“对上”,从而构造出一个有三列数据的新表,并且其中三列分别是LastName,DepartmentID,DepartmentName,那么就只用查一次表了,这个操作其实就是table的join操作。- % 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'9 B) S: b$ A8 z; z j, |
其中join函数的第一个参数叫做左表,第二个参数叫做右表。 t1用表格形式表示如Table.3所示,请读者自行核对。为了说明左连接,右连接和全连接,我们把表Table.1稍作修改,把最后一行Jasper的DepartmentID改成36,如表Table.4Table.3 join(A,B)2 e# z: N# w) e* v6 [0 O
Employee | DepartmentID | DepartmentName | Rafferty | 31 | Sales | Jones | 33 | Engineering | Steinberg | 33 | Engineering | Robinson | 34 | HR | Smith | 34 | HR | Jasper | 35 | Marketing |
7 Q; b+ E5 ?: @2 b. c! xTable.4 Employee表C+ |9 j2 T$ c. f/ p- q
Employee | DepartmentID | Rafferty | 31 | Jones | 33 | Steinberg | 33 | Robinson | 34 | Smith | 34 | Jasper | 36 |
$ e4 _* Q! R. T/ k h! V) w
1 h: ? l' i. _! C) M2 f$ d( ], g) I/ o
- S8 x( x8 i+ w# ?
" Q, e2 L+ K- }* K# n& H8 k8 e
% x/ l' M; ]% }" f) `
: O- P6 q; I6 b- a
9 x3 ^, {( s H/ s$ F
( X$ k7 S4 i- h& p
& @3 K* z' u5 }- ~; Z9 E N% `( Q" {* R! G
, T; h6 o; o1 r% y- D# w
; [& w# G; g+ D- Z. M1 i; j
所谓左连接,即连接结果表中将包含"左表"的所有记录, 即使那些记录在"右表" 没有符合连接条件的匹配。- % 左连接
- >> 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 '' %<-----
3 z% ?4 p& @2 D: ] 观察t3的结果,其中左表Table.4 中Jasper的DepartmentID是36,在表 Table.2中没有任何对应的行,但是左连接的结果t3中仍然保存了Japser项,并且其对应的DepartmentName为默认空字串。 所谓右外连接, 与左外连接完全类似, 只不过是作连接的表的顺序相反而已. 如果“左表”右连接“右表”, 那么"右表" 中的每一行在连接表中至少会出现一次. 如果 “右表”的记录在"左表"中未找到匹配行, 连接表中来源于“左表”的列的值设为默认空值。右表Table.2中的DepartmentID 35和36在表Table.4都没有任何员工与之对应,但是右连接的结果t4保留了这些没有员工对应的Department。- % 右连接
- >> 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' %<-----+ K0 `1 c$ X# G" N1 L
全连接是左右外连接的并集. 连接表包含被连接的表的所有记录, 如果缺少匹配的记录, 即以默认值填充。这允许我们查看每一个在部门里的员工和每一个拥有雇员的部门, 同时, 还能看到不在任何部门的员工以及没有任何员工的部门- % 全连接
- 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 '' %<-----
" b" U+ H9 ~. S, |% e8 } 内连接(inner join)是应用程序中用的普遍的"连接"操作,它一般都是默认连接类型。内连接基于连接谓词,即DepartmentID,将两张表的列组合在一起,产生新的结果表。查询会将 A 表的每一行和 B 表的每一行进行比较,并找出满足连接谓词的组合- % 内连接
- >> t5 = innerjoin(C,B)
- t5 =
- LastName DepartmentID DepartmentName
- ___________ ____________ ______________
- 'Rafferty' 31 'Sales'
- 'Jones' 33 'Engineering'
- 'Steinberg' 33 'Engineering'
- 'Robinson' 34 'HR'
- 'Smith' 34 'HR'" |6 w# T3 l+ n
t1和t5的结果类似,join和innerjoin的区别在于join对两个表的契合度要求更高,表1中的Key一定要在表2中也出现,如果尝试连接表3和表2,因为表C的Jasper的DepartmentID变成了36,而36在表2中不存在,MATLAB报错如下:- % 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] = lasterr
- a =
- 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
! N! d3 U9 i( X& {1 m5 o0 t + _* k2 d6 R& g3 ~5 i4 s
: D4 E0 p$ W; {! {% A
table的属性和支持的操作
- s) O9 q; I% G$ j
- K% |1 k/ D: G! n' I! @$ o最后做个总结,table是MATLAB从R2013b开始新引入的一个类(数据类型)。用UML(Unified Modeling Language)中的类图,可以表示如图 Figure.1Figure.1 table的Class Diagram4 }: J' t+ c1 ^% U9 B
) H( t7 x0 Q6 q
7 d9 _# o5 h5 ]8 S
! B* j3 a) e2 f) r, _2 W
图Figure.1中的属性除Properties外都是私有属性,即不可以用dot语法直接访问- % 通过Properties这个中间属性来访问table的其它属性
- >> t1.VariableNames
- You can not access the 'VariableNames' property directly. Access it using dot subscripting via .Properties.VariableNames.9 E, I+ a9 y M- f
按照错误信息的提示,我们可以通过Properties这个metadata来访问这些属性,表\ref{map_phone_book_table}对应的table中的Properties将返回如下的内容- % Properties作为访问table其它属性的中间层
- >> t1.Properties
- ans =
- Description: ''
- VariableDescriptions: {}
- VariableUnits: {}
- DimensionNames: {'Row' 'Variable'}
- UserData: []
- RowNames: {}
- VariableNames: {'Name' 'Number'}
- >> t1.Properties.VariableNames
- ans =
- 'Name' 'Number'
4 w) d+ p. S' ~4 L% @: S- b" p5 ? 图Figure.1中的中Import and export,Size and Shape, set, Data Organization操作代表一些列可以施加在table上的方法的集合。我们可以通过help命令来得到该类的帮助信息:- >> help table* E+ N$ L5 F: Z ^) D( S7 V2 b$ y
其中有这些方法的介绍,这里大致罗列如下,方便读者查阅。- Import and export类的操作* i6 e8 Q8 s T; X5 o
- eadtable 读入一个文件,创建table对象
- writetable 普通函数,把table写入一个文件,内部调用write
- write 类方法,把table写入一个文件) q7 K5 N9 X( `3 c6 t. I7 V
- Size and shape类的操作
$ C! W& q$ j. D* J( O- istable 判断一个变量是否是table类型
- size 返回table的高和宽,表头不计
- width 返回table的宽
- height 返回table的高
- ndims 返回table的维度
- numel 返回table高和宽的乘积
- horcat 横向串接table
- vercat 纵向串接table$ l( Y9 h3 e! u( G0 I6 |$ z$ E
- Set membership类的操作
& y: F5 `7 F: L9 Z3 m% m7 N- intersect 返回两表中的相同的行
- ismember 查询表中的行是否在另一表中也出现
- setdiff 查询两表之间的差异
- unique 返回的表中没有相同的行
- sextor 两个集合交集的非
- union 两个集合的并
- join 自然连接
- innterjoin 内连接
- outerjoin 外连接 j4 J1 r" h: F* T% M8 ^8 m8 t
- Data organization的操作
6 n" x) b( ^' p- summary 返回table的基本信息
- sortrows 给table按照制定的row排序
- stack 把table的各列摞成一列
- unstack 把table的某一列展开成为若干列
- ismissing 找到table中那些没有赋值的项,返回logical index
- standizeMissing 给未赋值项赋默认值
' h2 K i1 y7 ^# f1 C3 E- o
- vaRFun 把函数作用在table中选定的变量上
- rowfun 把函数作用在table的每列上
! h8 L" S# I! s1 G4 j" B
+ _$ y; r% A# }2 b0 T+ ^# f( I: G( S* s" l) o2 I
|
|