|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 uqHZau 于 2020-11-30 13:25 编辑 / a; K4 X5 X3 g) P7 v1 W
( U2 [+ w. m# S8 G( x; m( T
目录:2 z1 [1 J; E, g" e# U. v1 }$ T' l
- table简介
- 为什么需要table数据结构
- 通过导入数据构造table对象
- 调用table构造函数来构造table对象
- 通过转换函数构造table对象
- 访问table中的数据
+ A8 Y: R, y R8 D! E ' X9 e. S4 P1 d
MATLAB常用基本数据类型有:整型,浮点型,字符型,函数句柄,元胞数组和结构体数组。除了这些基本数据类型,MATLAB还有很多其它的数据类型不为人熟悉,这些数据类型在编程中也非常有用。MATLAB高级数据类型系列旨在向大家介绍它们:比如containers.Map, tables,enumeration和time series等等,它们为什么有用,用来解决什么问题,并且怎样在科学工程计算中怎么使用。上篇我们提到了映射表结构(containers.Map )。本篇将介绍另一中新的MATLAB数据类型--table。
; `! _4 S3 i3 N1 [; L# W) U6 i( E1 d: _3 r; Y% i
table简介
+ a7 M I: Z% i3 {- c% M" B6 Z为什么需要table数据结构
, q1 I l! J# T" _1 VMathWorks在MATLAB R2013b中引入了一种新的数据结构叫做table 。table类似统计 工具箱中的dataset ,其引入的目的就是用来取代dataset的数据类型。因为表状的数据在工程计算中越来越长久,有了table 类型,MATLAB用户就可以不用购买统计工具箱,也能使用表状的数据结构了。 table本质上来说是一种可以存放各种数据类型的容器,比如下面表Table.1中的数据,其中既有字符型,又有数值类型,其中第一行作为表头:Symbol,Name,Market,Cap,IPO, Year是各列的名字。
C* m# U! T' T6 C8 r3 z8 ~$ o7 ^2 J- U! \+ m
Table.1 NASDAQ股票名称表Symbol Name Market Cap IPO Year
, U3 S+ Z- ]- U" uAAPLApple Inc$742.63B1980 K% {9 w# r" j6 v* Z; q9 |
AMZNAmazon.com, Inc$173.33B1997
% O$ _/ Z; b) _- G( SMSFTMicrosoft Corporation$346.9B19861 N L: Q- S' y8 V! x- D$ U
在conatiners.Map的章节中,我们介绍了MATLAB的基本数据类型(比如数组,原胞数组和结构体)在表达某些复杂数据类型时的局限性。这里不再一一赘述,读者只需要认识到:数组的局限性在于不能用来存放数值以外的数据,而使用元胞读取和索引内容时有种种不方便,比如无法区分该数据中的表头和其余的行数据。事实上,如果数据存放在如下的CSV文件中,并且用importdata 直接读取表Table.2中的CSV文件。
9 R$ l h3 ?6 d6 ~1 f! B" L% r/ K3 ^% `$ J% m9 x- j8 P8 X
Table.2 Nasdaq 的 csv 原始数据, V1 G) q3 V, N5 ^/ N6 b
"Symbol","Name","Market Cap","IPO Year"# \$ A( ~9 @3 z0 F
"AAPL","Apple Inc","$742.63B",1980/ S2 r5 `0 J' F$ e6 i- w' p! t; b5 ^
"AMZN","Amazon.com Inc","$173.33B",1997
* a- B- u, A" y. `"MSFT","Microsoft Corporation","$346.9B",1986' s& E D. f( a% u
% R' \6 o& F4 Q" L, ]读入之后数据将会被分成数值和非数值部分:
; ?4 A' [5 ~; S1 X1 `0 N/ ^7 ?% 用importdata直接读入CSV文件
- h W" a/ a: m5 W, d>> nasdaq = importdata('nasdaq.csv')' O; q6 h3 [. P
nasdaq = % 结果存在struct中
$ a7 a! y* P9 \ T0 v4 C) ~0 k& S+ h: w data: [3x1 double]
1 j0 _( p3 K# z, [4 q) a# t& C textdata: {4x4 cell}
Y3 |3 X" V0 A# d1 b! o>> nasdaq.data % csv中的数值部分( g; a. }# w5 B% H+ e
ans =& r, G% I. @( X: _% `: F
19801 `; R; O- S- s9 t4 F, Z4 C, r
19970 z9 c% l( z5 E2 _3 C2 L
1986 / M. Q U1 s- E9 g m4 S3 z
>> nasdaq.textdata % csv中的字符部分% a+ C" w6 z" ^ s% K n! q
ans = x. E+ T4 @' ?5 Q1 V: q
'"Symbol"' '"Name"' '"Market Cap"' '"IPO Year"'
9 Z3 U- x) d; J+ }% k# n2 H" G3 O 'AAPL' 'Apple Inc' '$742.63B' ''
. t9 d- O- J! j$ `% Q 'AMZN' 'Amazon.com Inc' '$173.33B' '' 6 ]7 q( L; B! a5 x
'MSFT' 'Microsoft Corporation' '$346.9B' ''
4 V& t& X6 d( B& k$ A+ Z* ]3 ~8 I! C2 w
显然这不是我们所期待的要导入格式。5 J/ o+ U- Q7 S' s$ A! ^
4 K6 ]. Z1 b+ ]. R通过导入数据构造table对象6 K# C# ^6 I+ Z, _ v
沿用表Table.2中nasdaq.csv文件,我们可以使用readtable 函数,构造一个新的table对象,把csv文件中的数据导入到该对象中。readtable函数接受文件名称作为输入,返回一个table对象。
# @; \4 y6 |0 F C3 F+ B
, z$ U2 C$ ^, D" w; L0 ?/ n% 通过readtable函数来构造table对象$ o: W/ Q+ e) z
>> nasdaq = readtable('nasdaq.csv')2 K z/ E. I' H. i6 S" q
Warning: Variable names were modified to make them valid MATLAB identifiers. , H- q$ D: Z% y) p2 }
nasdaq = , J, l1 V+ s4 H4 }
Symbol Name MarketCap IPOYear- ]6 a1 L, e" K/ S; N8 ?- P
______ _______________________ __________ _______6 _# U/ t j+ }; u7 x Y
'AAPL' 'Apple Inc' '$742.63B' 1980
% j& ]& l6 M% j* S 'AMZN' 'Amazon.com Inc' '$173.33B' 1997
. _% h' }' [# i. {/ n9 w 'MSFT' 'Microsoft Corporation' '$346.9B' 1986 , v8 ]' `$ \% [- P" r) G
. n$ x# B" F I. | @$ G6 j注意第2行的warning,因为readtable 函数把nasdaq.csv中的第一行自动变成了这个table的表头,在创建table对象的时候,MATLAB会对做表头的文字做处理,这里把Market Cap和IPO Year两个词中的空格去掉,缩成一个词,这样做是为了方便将来使用dot语法来访问表中的数据。因为MATLAB修改了原来的表头,所以这里给出了warning。, a u( ~0 R: \# X
3 R0 z4 H t, b! G( M调用table构造函数来构造table对象8 k9 r- w- ^: [% ^! U/ b
我们还可以通过直接调用table类的构造函数来创建table对象 (什么是类的构造函数见参加<>第2.5节,构造函数和类的名称相同)。在containers.Map 的介绍中,我们举了电话号码簿的例子,如表Table.3所示,它是我们这节要构造的table对象的原始数据
- ^& m# ^/ \3 V9 d. O- ^/ `; c: S5 W8 J$ k& |) b7 {1 h# }3 h
Table.3 电话号码簿
& y$ q" V& ^- |$ r m8 j; _8 W& n: K' A9 K
姓名 电话号码 ; V8 L/ C4 o$ M$ Z: [
Abby50864700016 s+ C! K$ w; e
Bob5086470002/ D' m4 o! u) [' O( e
Charlie5086470003
. d; y: n+ E$ h, K: c( T" G6 ~下面程序中第1,2行用元胞数组来表示表中每一列的数据,第3行规定了表头的名称,第4行调用table的构造函数创建table对象,先输入数据,再输入表头的名称。表头通过table对象的VariableNames属性来设置。! Y. ]2 s# H' y+ W
B7 Q3 Y' |+ G/ fname={'Abby';'Bob';'Charlie'}; % 3x1列向量
/ u0 z- i+ U& Q3 v! J A1 enumber={'5086470001';'5086470002';'5086470003'}; % 3x1列向量9 I. {$ L0 k6 w0 W8 N
colName={'Name','Number'};6 N4 F k& t; P3 K7 b
phonetable=table(name,number,'VariableNames',colName)
4 q& Y& A& V w; |# f9 u8 M
: q; z* p5 l( u0 M7 L" s+ j @命令行显示如下# A6 q6 x. N' R9 b/ F* A/ \0 c
% Z; ?8 a0 b6 o6 o% phonetable在命令行中disp的结果
4 c/ M7 A2 t3 ^phonetable = + c! Y; C$ ^/ @. h- U O) r" ]
Name Number
. ^" B2 a" k: c' K1 d1 z n _________ ____________ K) `" }1 C9 p9 f+ [ g
7 P3 R+ \$ h k- R; V P/ s1 T 'Abby' '5086470001'4 k2 o& r( W6 n. v) ]' p
'Bob' '5086470002') }5 ~7 a% z' W# K
'Charlie' '5086470003'! T5 G6 \) \4 I- N4 j$ ~5 B
1 ?7 W$ g% D C
第4行把Name和Number做为table对象的VariableNames,可以这样理解VariableNames,我们可以把table看成由一个个列数据组成的数据结构,每列都是矢量,其中存放相同类型的数据。如果一个table有两列,它就有两个列矢量,每个列矢量都是table的一个变量(Variable),给变量名字就是Variable Name。+ x" J' Z( k5 ?' Q% a% w( L- h
8 H- R# n% C# E8 z0 p" B
通过转换函数构造table对象
* z; p; s8 {& b/ g6 G0 l, S除了使用table的构造函数来创建table对象,还可以使用转换函数把其它数据类型转成table,下列通过数组数据类型类构造table。下面的程序的1-2行,我们利用financial工具箱中的fetch函数,从Yahoo财经处得到雅虎从3月1日到3月10日的股票价格,fetch函数将返回一个数组,第3行我们利用array2table转换函数把得到数组转成table。
. H6 @2 _: o( { _" q5 f) f3 R& M+ c- R7 j' B8 s7 i6 ]4 j) A0 j
% 通过array2table创建table对象
u2 [8 K2 D2 w8 I t- qconn = yahoo;6 m4 d; d y% R8 ]" a, {
array = fetch(conn,'YHOO','3/1/2015','3/10/2015');5 e( V- N6 G0 j7 `3 G: {
yhoo = array2table(array,...
' h0 E4 @# c4 T% t$ c+ e 'VariableNames', {'date','open','high','low','closing','volumn','adjusted'})& G$ ]4 a1 K W6 H. ^% C
! m5 a1 G' S% _( Z
第4行中,我们通过VariableName来指定表头的内容,结果显示如下
" w+ u, {! {- N+ O
* D1 e' o' d/ Z6 f6 Z: T% yhoo的table在命令行的显示: r0 o% H/ L9 M" s# y
yhoo =
9 k5 z+ c) Q4 |: q! {8 i date open high low closing volumn adjusted
# g3 ]6 j) G4 g6 G# L; j( i __________ _____ _____ _____ _______ __________ ________
9 E* L( c7 ^7 K1 k. R 7.3603e+05 42.57 42.92 42.18 42.68 1.0601e+07 42.68 ' d) O& M+ j& t3 n
7.3603e+05 43.6 43.93 42.67 42.98 1.1802e+07 42.98
/ A* V& e: W1 n1 Q 7.3603e+05 43.98 44.24 43.4 43.44 1.1888e+07 43.44 # b: X- Q$ G) m& {5 y+ k0 y5 `
7.3603e+05 44.18 44.31 43.5 44.16 1.1868e+07 44.16 t' J& a6 ]+ f) g
7.3603e+05 42.08 44.38 41.97 43.99 3.0099e+07 43.99 8 Y) h: s# p7 e- y7 c. K
7.3603e+05 43.7 43.95 42.42 42.62 2.2392e+07 42.62 ! J) q! w$ t- G4 C+ A8 X. x
7.3603e+05 44.06 44.43 43.7 44.11 1.1027e+07 44.11
$ m, ~5 K' i1 ]1 Y
/ @) E/ a _4 A4 p% V9 I访问table中的数据
, a+ v5 x/ ?* @ w, J) [; w" U" ]# k
! _' C5 {8 G6 j& x( P. ~通过表Table.1所建立的table对象,在命令行中显示如下:
) N) |1 [6 n& ^8 T) @8 K Z% ]
4 H. C5 ~' V! a5 g5 n6 j5 ]( z+ z5 u! t% nasdaq table在命令行中的显示' _4 b5 {; c, _- J
nasdaq =
: v9 Z; J j0 v% ? Symbol Name MarketCap IPOYear) }) ~% \# X" S7 ^2 i7 e
______ _______________________ __________ _______
8 q! w$ h+ }) W1 [$ l1 {* P6 x( q+ g, K$ o
'AAPL' 'Apple Inc' '$742.63B' 1980 1 e, z" Z( N% m5 @6 h, K
'AMZN' 'Amazon.com Inc' '$173.33B' 1997
3 _; {! @: `2 E5 R 'MSFT' 'Microsoft Corporation' '$346.9B' 1986
& _7 D+ C% s( d) c$ P& ~3 ]* W$ b* L- u9 i c) t6 @
我们可以通过使用dot+Variablename的语法直接访问table中的列,返回的结果是cell格式的数据:" ?8 l' Y" d- P' s3 f4 T8 N
2 u. \' m1 G: h3 A1 s) x2 t2 u$ ?% w% 使用dot语法访问table中的数据( t5 t/ `+ S8 Y0 L6 M2 Q
>> nasdaq.Symbol % dot格式+变量名的访问方式 T8 a, |! Z/ I
ans =
) M' a- |# Z2 g, I X% i# f 'AAPL'
& V. ?0 O3 V5 p+ W& V 'AMZN'
3 s6 q, L" g0 [! I0 a6 \. s5 k 'MSFT'& g/ L Q ?- F5 [6 x$ Z
>> class(nasdaq) % 返回cell格式的数据
1 v4 \* h& c1 w9 Q- \ans =. }( V% ~: P; g# ^0 q3 x# c
cell
" }# M r1 D( y; G" A' W8 H& X: h' N: v
table类重载了subsref函数(什么是运算符的重载,参加《MATLAB面向对象编程-从入门到设计模式》12.1节),于是支持MATLAB传统的圆括号下标访问,如果要访问第一行,则:' A7 U$ m6 f! W2 D
* w: b) f I$ M) |: K% 使用下标语法访问table中的数据6 B0 \) P* ~* j1 {+ P9 V ]3 G z
>> nasdaq(1,:)
' a4 t3 V% \+ _% }( e, H" [& D, Kans =
( e% _4 w% V" z0 W/ o Symbol Name MarketCap IPOYear
8 x" N- y3 R+ z6 ~ ______ ___________ __________ _______
9 E8 [7 u) q- M2 i! E6 ]! p4 M' u! `) Q" K
'AAPL' 'Apple Inc' '$742.63B' 1980 8 l0 F Z7 v: j; [" Y
8 x% B" D" f% H" C4 \3 I
使用圆括号,返回的结果仍然是table,如果要访问第2到3行,则:
* Y0 @, ]% {4 `) F; Z* c. |+ u/ x( ]
+ J2 h& Q0 l. w. M; I' N3 g% 使用下标语法访问table中的数据4 {. M) m+ ^# Y6 V. {
>> nasdaq(2:3,:)4 f4 e5 l3 i5 B: a( N# M
ans =
% r) m6 W3 c. a8 H5 c/ o1 ~; h& W Symbol Name MarketCap IPOYear! \ a- h* K9 \: l
______ _______________________ __________ _______
# G0 x9 ?( E" n! Z1 d n" X" [! {
'AMZN' 'Amazon.com Inc' '$173.33B' 1997
7 X: Q$ R5 \. Q9 O 'MSFT' 'Microsoft Corporation' '$346.9B' 1986
5 n( \- [* `6 r% {+ c. D4 R# R! A8 N
返回的结果仍然是table。 table数据结构支持MATLAB传统的花括号下标访问,返回的结果是cell格式的数据
9 r: M- b" r0 z! w5 y # X7 i" Y# i E3 F7 ~
% 花括号下标访问
( r/ o- s! N" p>> nasdaq{:,1} % 花括号下标访问,返回第一列中的数据
8 O( H8 P7 Z/ b% ?5 G* t8 aans =
- k$ p) L: {+ n& J6 ? 'AAPL'
3 b+ Y- L, }" X% L3 }7 S, { 'AMZN' ~) R' M; N2 r" j$ f1 ]/ P
'MSFT' / T9 C/ H2 h& X7 n
: v, o; E1 G% P0 _
还可以把Dot语法和下标语法结合起来获取数据,下例代码访问table第一列的第三行,返回的结果是元胞。
/ g( E9 I6 D+ i$ D* S" i$ D9 w3 ]( G
% Dot语法和圆括号下标访问结合
# j; V8 N! }3 v+ }4 }>> nasdaq.Symbol(3)6 _+ m( c* _7 J
ans = 2 Z$ o" Z) }6 |. M" m. T
'MSFT'
/ r- V8 A( `: W+ N0 m, v>> class(ans) % 圆括号下标访问,返回结果是元胞
! d8 u6 s) {. W! l! fans =0 l% r( H" a& [3 e) f8 m" g
cell 7 F7 T I! `4 e9 E. H7 L
|
|