|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 uqHZau 于 2020-11-30 13:25 编辑
2 U+ h8 r' @% m! Z; v6 |: M, D( p; ^# ~: Y W# P; M0 m! S
目录:
: ~' @) {- p" M7 v0 k! R: p) ?- table简介
- 为什么需要table数据结构
- 通过导入数据构造table对象
- 调用table构造函数来构造table对象
- 通过转换函数构造table对象
- 访问table中的数据
8 Y( z7 E: U2 m0 _5 c! v0 @ / H9 k, p. n/ r3 J. J9 v
MATLAB常用基本数据类型有:整型,浮点型,字符型,函数句柄,元胞数组和结构体数组。除了这些基本数据类型,MATLAB还有很多其它的数据类型不为人熟悉,这些数据类型在编程中也非常有用。MATLAB高级数据类型系列旨在向大家介绍它们:比如containers.Map, tables,enumeration和time series等等,它们为什么有用,用来解决什么问题,并且怎样在科学工程计算中怎么使用。上篇我们提到了映射表结构(containers.Map )。本篇将介绍另一中新的MATLAB数据类型--table。
) @( M* a4 {0 ^' F6 t' a* W) A5 t2 s; R+ |6 n9 r" w e
table简介' a& S$ S1 x% B2 t! a2 a
为什么需要table数据结构1 N. Z5 v' B' e! r+ ^$ P
MathWorks在MATLAB R2013b中引入了一种新的数据结构叫做table 。table类似统计 工具箱中的dataset ,其引入的目的就是用来取代dataset的数据类型。因为表状的数据在工程计算中越来越长久,有了table 类型,MATLAB用户就可以不用购买统计工具箱,也能使用表状的数据结构了。 table本质上来说是一种可以存放各种数据类型的容器,比如下面表Table.1中的数据,其中既有字符型,又有数值类型,其中第一行作为表头:Symbol,Name,Market,Cap,IPO, Year是各列的名字。
7 P V! }% Q d% r3 O2 ^/ V3 n" a" u' P* P: | s- R
Table.1 NASDAQ股票名称表Symbol Name Market Cap IPO Year
- c0 W5 @1 w* s0 q+ Z# @4 O# qAAPLApple Inc$742.63B1980/ L0 W. x. ~7 U( V
AMZNAmazon.com, Inc$173.33B19972 B' c& O$ |. N9 y2 d
MSFTMicrosoft Corporation$346.9B19860 p7 r, g9 q! G+ m. d
在conatiners.Map的章节中,我们介绍了MATLAB的基本数据类型(比如数组,原胞数组和结构体)在表达某些复杂数据类型时的局限性。这里不再一一赘述,读者只需要认识到:数组的局限性在于不能用来存放数值以外的数据,而使用元胞读取和索引内容时有种种不方便,比如无法区分该数据中的表头和其余的行数据。事实上,如果数据存放在如下的CSV文件中,并且用importdata 直接读取表Table.2中的CSV文件。
9 g3 [7 A/ F. Z+ Q# m
: j2 ?5 h: A" i5 B, ^6 g1 lTable.2 Nasdaq 的 csv 原始数据
/ B5 C0 r- W$ q( `"Symbol","Name","Market Cap","IPO Year"
8 T* c3 x% m" ~) S( t; a3 j, b"AAPL","Apple Inc","$742.63B",1980
% H: c2 r! @/ U8 I9 ~; f$ A"AMZN","Amazon.com Inc","$173.33B",1997 R2 a* v8 I" ~6 a* a$ D+ c
"MSFT","Microsoft Corporation","$346.9B",1986
1 \6 }# r' Z+ n/ b; r, O: C. ~) d V! v, M$ o
读入之后数据将会被分成数值和非数值部分:$ i+ v* P! h# c5 n
% 用importdata直接读入CSV文件
! Z' b4 ^2 p }7 C3 o# j>> nasdaq = importdata('nasdaq.csv')' s5 i& t/ F) q/ R- t* ?0 a; L
nasdaq = % 结果存在struct中) U: P2 C2 D* C+ s2 O
data: [3x1 double]' P$ g) i0 j: A8 v) @) w
textdata: {4x4 cell}* c' h4 Y7 L9 w3 y- S
>> nasdaq.data % csv中的数值部分8 J6 @6 O+ N8 O }
ans =
" D+ P+ v6 R: z1 n 1980
, G* ^( z4 k6 E& [ M 1997
/ T2 n/ Q; i/ l# |- L3 F- a: C 1986
* t& v- q: E0 R# D) Q( h>> nasdaq.textdata % csv中的字符部分$ }( r# l) C" ]$ n; d, F
ans = " b( j9 o/ d* R' L
'"Symbol"' '"Name"' '"Market Cap"' '"IPO Year"'
9 w: x) M/ @0 x n4 Y" Z/ V' J 'AAPL' 'Apple Inc' '$742.63B' '' 7 v' G3 y/ S4 ?! t" ~
'AMZN' 'Amazon.com Inc' '$173.33B' ''
+ M6 k" n9 Z# O# s 'MSFT' 'Microsoft Corporation' '$346.9B' ''
3 |0 `; [2 r. R' x8 d4 b
8 h) n5 a( R% _' z# f显然这不是我们所期待的要导入格式。
, L9 i% Z6 v. Y, }- Q, [6 A" w# c2 v( q$ D" _# M5 I1 [- m2 @+ `, k1 _
通过导入数据构造table对象: @8 Q6 b6 d* D/ j0 d
沿用表Table.2中nasdaq.csv文件,我们可以使用readtable 函数,构造一个新的table对象,把csv文件中的数据导入到该对象中。readtable函数接受文件名称作为输入,返回一个table对象。+ a1 J* L) m+ Y+ A5 J
8 u3 }# U( v4 C/ N( c. x; r
% 通过readtable函数来构造table对象
E4 c2 U6 I. M; ?1 p4 x* e/ _>> nasdaq = readtable('nasdaq.csv')
z4 ]. o5 i$ y$ v5 CWarning: Variable names were modified to make them valid MATLAB identifiers. + j6 p' U# G' R
nasdaq =
2 q. f& [/ z0 D7 z+ u Symbol Name MarketCap IPOYear
! `: u( a" S7 [9 ^ ______ _______________________ __________ _______; W6 r! J( |1 S. v4 k+ O
'AAPL' 'Apple Inc' '$742.63B' 1980
& {% ^$ A3 E$ I$ U, K 'AMZN' 'Amazon.com Inc' '$173.33B' 1997 + Y4 Y7 t) y1 Q' V% _+ q+ Z+ \
'MSFT' 'Microsoft Corporation' '$346.9B' 1986
0 b) p `: l2 }0 t7 z8 G7 P) Z ]+ N+ r% S6 |+ `) U
注意第2行的warning,因为readtable 函数把nasdaq.csv中的第一行自动变成了这个table的表头,在创建table对象的时候,MATLAB会对做表头的文字做处理,这里把Market Cap和IPO Year两个词中的空格去掉,缩成一个词,这样做是为了方便将来使用dot语法来访问表中的数据。因为MATLAB修改了原来的表头,所以这里给出了warning。) d" m4 f0 }% ?3 l2 Y4 X9 ]$ W5 f
. c7 V; R. W$ r* y9 V! X0 _" [调用table构造函数来构造table对象! N5 |$ C8 i0 ?4 ?' G( a
我们还可以通过直接调用table类的构造函数来创建table对象 (什么是类的构造函数见参加<>第2.5节,构造函数和类的名称相同)。在containers.Map 的介绍中,我们举了电话号码簿的例子,如表Table.3所示,它是我们这节要构造的table对象的原始数据/ l. R# v j6 r ^+ _7 q8 R3 [
5 o+ N& Y# t& u9 I b/ rTable.3 电话号码簿* N( w! {- y2 N4 t0 W! P
# _7 Z7 f4 b6 T+ i姓名 电话号码
7 b% _- L* G2 p# K4 ?Abby5086470001$ e9 B$ A' `, J$ E' t2 @/ W7 e9 F
Bob5086470002( I. j2 m+ B2 l8 U, A
Charlie5086470003
- b- @7 |$ i- i' b1 \9 N; v下面程序中第1,2行用元胞数组来表示表中每一列的数据,第3行规定了表头的名称,第4行调用table的构造函数创建table对象,先输入数据,再输入表头的名称。表头通过table对象的VariableNames属性来设置。
) K) V& }( ~" a# l/ k% C9 j$ e2 A* i+ u# |; M
name={'Abby';'Bob';'Charlie'}; % 3x1列向量5 o9 M& \% T" H0 A% O/ f |2 r
number={'5086470001';'5086470002';'5086470003'}; % 3x1列向量
& X% k2 h+ y$ U, z* H& zcolName={'Name','Number'};) N' ?' l z- Z- p5 D# q' I$ @/ m
phonetable=table(name,number,'VariableNames',colName) " p, q) s1 `0 _: N; a
! \8 w* W9 t, F( b0 C2 a
命令行显示如下
$ R, U2 E$ M! z' f" Z8 W7 r1 ?9 ^) C3 A3 I* s G. a$ Z; P9 c
% phonetable在命令行中disp的结果 + F1 B# m" T% T+ e Y
phonetable =
% \* T$ V: \3 a% N& b Name Number I" F: Q3 U7 [: Y1 a9 ^
_________ ____________
. u* E5 k: |* P8 W
b' f5 ~; l4 n7 N 'Abby' '5086470001'% F( {8 K. ^$ {6 j+ H0 L0 p
'Bob' '5086470002'
, |% N) v5 O4 D 'Charlie' '5086470003'' }/ s0 n. X1 T4 k: K
$ N1 _+ ~7 B$ K+ @
第4行把Name和Number做为table对象的VariableNames,可以这样理解VariableNames,我们可以把table看成由一个个列数据组成的数据结构,每列都是矢量,其中存放相同类型的数据。如果一个table有两列,它就有两个列矢量,每个列矢量都是table的一个变量(Variable),给变量名字就是Variable Name。7 p" E* }1 |% D/ v4 G" H+ n
- @6 \5 ~; e0 E1 S
通过转换函数构造table对象
/ ]# T, x% ?: t除了使用table的构造函数来创建table对象,还可以使用转换函数把其它数据类型转成table,下列通过数组数据类型类构造table。下面的程序的1-2行,我们利用financial工具箱中的fetch函数,从Yahoo财经处得到雅虎从3月1日到3月10日的股票价格,fetch函数将返回一个数组,第3行我们利用array2table转换函数把得到数组转成table。0 Z! s0 K5 v9 d5 T |
% F _& y! \; X8 r+ c, k! v/ s% 通过array2table创建table对象
/ r: d- C: |0 oconn = yahoo;
* I! m# _+ I- f0 E, |3 Sarray = fetch(conn,'YHOO','3/1/2015','3/10/2015');+ }) Z# h0 K2 h4 H3 G
yhoo = array2table(array,...3 l9 ~! u) D7 L
'VariableNames', {'date','open','high','low','closing','volumn','adjusted'})
g2 s. j5 x; S; o5 W. J1 K" F
第4行中,我们通过VariableName来指定表头的内容,结果显示如下) d' A! n+ y) p2 q; O
{) ?4 ?' y. C5 w" J
% yhoo的table在命令行的显示7 g- v: l9 p, H/ H
yhoo = & v @7 `) \6 c) }% y
date open high low closing volumn adjusted
: ]6 _- W- @& N: i1 ~ __________ _____ _____ _____ _______ __________ ________6 l4 W( N- f& _8 h+ z- P7 T
7.3603e+05 42.57 42.92 42.18 42.68 1.0601e+07 42.68
; Q: l. g( L; l- Y+ k 7.3603e+05 43.6 43.93 42.67 42.98 1.1802e+07 42.98 + ~" |7 i( I' [: c
7.3603e+05 43.98 44.24 43.4 43.44 1.1888e+07 43.44 4 F G7 K5 {' @0 N6 k
7.3603e+05 44.18 44.31 43.5 44.16 1.1868e+07 44.16 , z$ C4 O9 V; p; V8 v. ~% n# I6 L
7.3603e+05 42.08 44.38 41.97 43.99 3.0099e+07 43.99 8 D$ g* |7 T) f# }2 V
7.3603e+05 43.7 43.95 42.42 42.62 2.2392e+07 42.62 $ f) b( U8 X* A7 G/ \ U) ]
7.3603e+05 44.06 44.43 43.7 44.11 1.1027e+07 44.11
3 G- w& L* c$ K6 l d7 z2 ~% i" K E7 I. h! |! f$ }$ q
访问table中的数据
0 ]% b! {, q" b) d* x' g. R2 x* I% R" }* K' N4 M
通过表Table.1所建立的table对象,在命令行中显示如下:
1 }6 {. u: q: E/ O* c
) d( G2 \9 W# w4 o6 l% nasdaq table在命令行中的显示1 {8 w2 a \2 }9 r4 z( d
nasdaq =
# g0 t; M2 @( u$ K3 z Symbol Name MarketCap IPOYear; g5 _& w2 v, K, d- |! y
______ _______________________ __________ _______# t0 U, e Z Z& ^/ C
; S5 E. B, i/ Q 'AAPL' 'Apple Inc' '$742.63B' 1980 - L- i1 v+ h# \+ G% c
'AMZN' 'Amazon.com Inc' '$173.33B' 1997 _0 U3 t! s9 C- n* \ D
'MSFT' 'Microsoft Corporation' '$346.9B' 1986 2 f! j, C7 B, j7 Z& ]5 |, K
- J* w/ p( I) X& h我们可以通过使用dot+Variablename的语法直接访问table中的列,返回的结果是cell格式的数据:1 X( r% o2 c; p: i+ ^+ r
: P* W" I( ~5 P/ S. f; U. S# x* e% G
% 使用dot语法访问table中的数据
( F, Y, q4 n2 o% j' F>> nasdaq.Symbol % dot格式+变量名的访问方式4 I+ P& o; ?% f7 v6 I! r
ans =
2 e1 h) L; a8 P, J1 x 'AAPL'( `$ ^5 t9 S- k2 ~6 `
'AMZN'
' g7 H$ m) |2 M' `: s2 z! u 'MSFT'; U4 ]/ d- |/ V1 U9 A) l$ R0 E( v
>> class(nasdaq) % 返回cell格式的数据
9 ], _9 k% W6 d% `4 N! vans =
3 Y8 p+ w* _0 ccell
4 |+ T7 z+ I0 z- \- A" ^1 b7 w+ Z* ~( m7 O/ m
table类重载了subsref函数(什么是运算符的重载,参加《MATLAB面向对象编程-从入门到设计模式》12.1节),于是支持MATLAB传统的圆括号下标访问,如果要访问第一行,则:
l( _8 k$ y, N& R, t6 _4 n' B6 Q* J# r6 v2 n a
% 使用下标语法访问table中的数据
, @" }, J' t4 M: D6 S4 X>> nasdaq(1,:)
6 _9 A0 f& M5 ?, h2 A: oans =
! u7 q0 C& A5 A4 Z% m$ U Symbol Name MarketCap IPOYear9 X$ a" k0 K, W4 o5 Z
______ ___________ __________ _______6 n7 l, A3 H+ I7 Y5 y; q
/ ~% v9 n9 J3 i
'AAPL' 'Apple Inc' '$742.63B' 1980
) |" V$ D* m: @6 \/ B) f8 A0 O0 W# J# L1 Q$ }: b( Q
使用圆括号,返回的结果仍然是table,如果要访问第2到3行,则:
- m& _' x- C, m
7 A. [! t# A8 m5 ~% 使用下标语法访问table中的数据2 g1 i& b. M: r9 r$ l" j- E
>> nasdaq(2:3,:)5 }2 f% P4 y. k
ans =
7 x- V$ R) A/ G: G2 R Symbol Name MarketCap IPOYear
0 n- L$ D$ c# y9 J9 r ______ _______________________ __________ _______
7 U: b+ a7 I2 X3 t8 A
3 b9 R( c0 @2 S$ I. B$ r) y* ^ 'AMZN' 'Amazon.com Inc' '$173.33B' 1997 6 ?7 W7 T9 B' w& `+ x
'MSFT' 'Microsoft Corporation' '$346.9B' 1986
$ b w) T* W/ P1 W& c! p' K, {% b# D7 A
返回的结果仍然是table。 table数据结构支持MATLAB传统的花括号下标访问,返回的结果是cell格式的数据$ f& F5 @5 ]4 H% D' x/ F/ a) M/ I( G
1 Y& [: F N3 ?' R' f) |9 H
% 花括号下标访问 a7 V9 C0 D. F/ ]$ J8 j
>> nasdaq{:,1} % 花括号下标访问,返回第一列中的数据3 \2 Y* a5 B( X' h* D8 t
ans = / L9 W3 X" j# D. e E
'AAPL'
9 B3 u' m$ n% j8 ]* w8 T 'AMZN'
) I& [ k& W: Y0 i% C0 K 'MSFT'
' Z5 T9 _8 h* y4 W# k5 f9 e
3 v0 X6 W! ~ T, G/ Z还可以把Dot语法和下标语法结合起来获取数据,下例代码访问table第一列的第三行,返回的结果是元胞。
( `4 v: t, j/ o( _! g0 ^2 | G8 B& [" ]9 }6 H3 N* v" H; B* w
% Dot语法和圆括号下标访问结合
7 r3 y3 c) o O>> nasdaq.Symbol(3): y# g3 u0 U+ \+ l' a- |2 f" Q
ans =
; s7 C$ N, P1 m: y4 Y$ W 'MSFT'
' r$ D/ l1 x/ b& b) x>> class(ans) % 圆括号下标访问,返回结果是元胞
0 H# G$ D' b- i4 I3 P+ F) Bans =1 H2 E! Y+ m* ]* l9 E
cell
6 g5 b2 T) M9 h, ]7 l* n, a3 B |
|