|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 uqHZau 于 2020-11-30 13:25 编辑
+ H& r9 K9 n1 r' T- R1 H2 p. l; K8 E; a6 p D
目录:
1 X" h- D/ G) o r- table简介
- 为什么需要table数据结构
- 通过导入数据构造table对象
- 调用table构造函数来构造table对象
- 通过转换函数构造table对象
- 访问table中的数据
( d9 Q4 Q% Y- m/ e- G. c7 W/ m8 w5 L 4 `; I* H2 `1 C; x4 f5 n# v
MATLAB常用基本数据类型有:整型,浮点型,字符型,函数句柄,元胞数组和结构体数组。除了这些基本数据类型,MATLAB还有很多其它的数据类型不为人熟悉,这些数据类型在编程中也非常有用。MATLAB高级数据类型系列旨在向大家介绍它们:比如containers.Map, tables,enumeration和time series等等,它们为什么有用,用来解决什么问题,并且怎样在科学工程计算中怎么使用。上篇我们提到了映射表结构(containers.Map )。本篇将介绍另一中新的MATLAB数据类型--table。
; `" J% e$ w0 d2 P7 ^
" O& z2 K: [- p& D# R9 l9 Gtable简介& i2 j8 v i6 |) L. O, z
为什么需要table数据结构
2 W% ]; {# F$ |MathWorks在MATLAB R2013b中引入了一种新的数据结构叫做table 。table类似统计 工具箱中的dataset ,其引入的目的就是用来取代dataset的数据类型。因为表状的数据在工程计算中越来越长久,有了table 类型,MATLAB用户就可以不用购买统计工具箱,也能使用表状的数据结构了。 table本质上来说是一种可以存放各种数据类型的容器,比如下面表Table.1中的数据,其中既有字符型,又有数值类型,其中第一行作为表头:Symbol,Name,Market,Cap,IPO, Year是各列的名字。
1 y( [+ ^1 r. k- k0 v
3 O- M4 C6 i( t8 J9 e* D0 z; y- zTable.1 NASDAQ股票名称表Symbol Name Market Cap IPO Year
( S! {- b% L3 a1 `AAPLApple Inc$742.63B1980
) k1 G- J1 e/ EAMZNAmazon.com, Inc$173.33B1997
" b5 v p/ j6 e& @4 X* \MSFTMicrosoft Corporation$346.9B19864 A: i2 g3 V! d7 r- C4 o8 E* \
在conatiners.Map的章节中,我们介绍了MATLAB的基本数据类型(比如数组,原胞数组和结构体)在表达某些复杂数据类型时的局限性。这里不再一一赘述,读者只需要认识到:数组的局限性在于不能用来存放数值以外的数据,而使用元胞读取和索引内容时有种种不方便,比如无法区分该数据中的表头和其余的行数据。事实上,如果数据存放在如下的CSV文件中,并且用importdata 直接读取表Table.2中的CSV文件。
) e' Q% f% Z# s) t
( f8 k3 ?. ^. B9 [Table.2 Nasdaq 的 csv 原始数据
( j: Q' A6 `; ?- p' G* ["Symbol","Name","Market Cap","IPO Year"
5 d. c( N; S& }' ^! `1 Z5 G/ w* g"AAPL","Apple Inc","$742.63B",1980
5 Y# O) w: U$ m4 E1 I. D"AMZN","Amazon.com Inc","$173.33B",1997
/ K0 M% ^3 s. B+ \% }% q"MSFT","Microsoft Corporation","$346.9B",1986
9 ]/ H3 ~( W/ w7 R2 z4 H! c1 I
读入之后数据将会被分成数值和非数值部分:
( U w* i6 Q* w* ]. H% 用importdata直接读入CSV文件6 x. U0 F* n D. \, T6 I* ^
>> nasdaq = importdata('nasdaq.csv')
: d7 R7 E( |6 U9 L) Hnasdaq = % 结果存在struct中+ x9 d. v3 V! U& @1 `- `' p
data: [3x1 double]" G4 H% X2 s9 ~' d& K ?& Z/ T H
textdata: {4x4 cell}
# a8 s# {% C2 O8 b7 u>> nasdaq.data % csv中的数值部分
0 i# Y8 @/ Z5 O3 N. r# wans =) S, v- K# h! D7 d6 p
1980
% b# f! I8 P# y2 K, d6 A 1997
3 B! g% _; Y k2 p# a/ _ 1986
S4 g- r. H: ^+ ]>> nasdaq.textdata % csv中的字符部分
! {6 r; b( {1 N% ?2 Q) Y7 |1 O ians =
8 o" Y A. v! s) L '"Symbol"' '"Name"' '"Market Cap"' '"IPO Year"'
2 |, l; Y' a {- ^8 V- ]) | 'AAPL' 'Apple Inc' '$742.63B' '' 0 D2 Y' l& d8 p% c9 m' q
'AMZN' 'Amazon.com Inc' '$173.33B' '' # _' y7 q+ k( K( w/ K
'MSFT' 'Microsoft Corporation' '$346.9B' ''
% H1 y6 N. A$ R6 `7 }( h7 _$ ?) S2 ~# S$ y W
显然这不是我们所期待的要导入格式。
, ^, [9 Y: B' T+ V7 Y0 U" P* B
0 t) O( Q& q W7 K4 `8 y. W3 \2 D通过导入数据构造table对象
7 S3 @0 e8 E. T9 m5 \沿用表Table.2中nasdaq.csv文件,我们可以使用readtable 函数,构造一个新的table对象,把csv文件中的数据导入到该对象中。readtable函数接受文件名称作为输入,返回一个table对象。/ J& G% v0 A& u
% j% K+ ]1 s. e% 通过readtable函数来构造table对象! \. F$ A/ T0 k* y, ?
>> nasdaq = readtable('nasdaq.csv')
' N; h6 [- S9 r$ _( n W; yWarning: Variable names were modified to make them valid MATLAB identifiers. * C* n; i4 N+ e
nasdaq = + E3 x9 q; U. D8 B8 @% {- I
Symbol Name MarketCap IPOYear
) p5 b/ ^, B, E& G8 v0 l8 W ______ _______________________ __________ _______* A- C& ~; J) S5 ^, Z7 I
'AAPL' 'Apple Inc' '$742.63B' 1980 + g4 ` ?% i( z7 o" Q
'AMZN' 'Amazon.com Inc' '$173.33B' 1997 % }5 Y& `; c, i/ t5 U% p8 y, ?
'MSFT' 'Microsoft Corporation' '$346.9B' 1986 ' |# x6 g, l5 m% g9 \7 B
% H7 _9 U7 a) ?, x: n注意第2行的warning,因为readtable 函数把nasdaq.csv中的第一行自动变成了这个table的表头,在创建table对象的时候,MATLAB会对做表头的文字做处理,这里把Market Cap和IPO Year两个词中的空格去掉,缩成一个词,这样做是为了方便将来使用dot语法来访问表中的数据。因为MATLAB修改了原来的表头,所以这里给出了warning。4 z- Q0 m. V3 j) j, u# N
& |) O S' o) k: t) X d/ ^
调用table构造函数来构造table对象% a7 t7 p( C0 C7 c* p) m
我们还可以通过直接调用table类的构造函数来创建table对象 (什么是类的构造函数见参加<>第2.5节,构造函数和类的名称相同)。在containers.Map 的介绍中,我们举了电话号码簿的例子,如表Table.3所示,它是我们这节要构造的table对象的原始数据. Y+ C6 w+ Y; l7 a
' u" c H, ~* M0 J/ k& YTable.3 电话号码簿) W) f% z6 D! m( o5 B2 ~# w8 r
# f; a$ g8 V; h6 t
姓名 电话号码
9 J0 f _/ Y+ P% I% Q! MAbby5086470001
{' y3 a& `- [9 e. o' u1 x% sBob5086470002
$ o K) x' \7 ^Charlie5086470003
9 n& E5 G4 @5 _/ B3 |下面程序中第1,2行用元胞数组来表示表中每一列的数据,第3行规定了表头的名称,第4行调用table的构造函数创建table对象,先输入数据,再输入表头的名称。表头通过table对象的VariableNames属性来设置。2 \6 i* l2 J9 M6 ]
8 h6 u% a2 A6 p: [0 v5 T; U
name={'Abby';'Bob';'Charlie'}; % 3x1列向量0 q) [0 D! j4 O9 I
number={'5086470001';'5086470002';'5086470003'}; % 3x1列向量9 A" H" F9 _9 N2 P' i9 c2 `' G+ }8 r
colName={'Name','Number'};
: m7 g5 r, D( d$ @phonetable=table(name,number,'VariableNames',colName) 2 s/ `9 {. M* H
- l/ @8 H, E$ x( f4 w% R命令行显示如下
$ A& N$ j/ @! q
0 \, M8 L, p+ }% phonetable在命令行中disp的结果
& @+ l( L' [& _2 s. g: h; ^phonetable =
& `9 v7 e; g' d# i% q3 ~- o8 B Name Number
P0 b: L6 B8 Q e- f _________ ____________
8 D& E+ u8 ^, n4 w! o7 s" O# ~. j: u* x4 f- Z, g( X9 E
'Abby' '5086470001'
/ O4 q3 I0 S7 ~3 Q; B 'Bob' '5086470002'
6 u3 g y5 L8 Q3 |4 L' a5 X0 q 'Charlie' '5086470003'
# b% g' h1 S2 @4 O
1 c1 ~/ G2 O7 e- P- g# [" }第4行把Name和Number做为table对象的VariableNames,可以这样理解VariableNames,我们可以把table看成由一个个列数据组成的数据结构,每列都是矢量,其中存放相同类型的数据。如果一个table有两列,它就有两个列矢量,每个列矢量都是table的一个变量(Variable),给变量名字就是Variable Name。
+ B. V2 ^6 {. T3 ?7 C0 Y
1 i O+ @" z1 I$ n5 d; D通过转换函数构造table对象
5 Z5 y! `! l$ H9 K除了使用table的构造函数来创建table对象,还可以使用转换函数把其它数据类型转成table,下列通过数组数据类型类构造table。下面的程序的1-2行,我们利用financial工具箱中的fetch函数,从Yahoo财经处得到雅虎从3月1日到3月10日的股票价格,fetch函数将返回一个数组,第3行我们利用array2table转换函数把得到数组转成table。3 V$ U' ~2 W% A9 L, s8 e G U \
6 d5 h+ F' Q$ l: y) @% 通过array2table创建table对象
8 i/ h7 }6 H, W0 J- U$ }conn = yahoo;
; Y$ z# t, s' S; Aarray = fetch(conn,'YHOO','3/1/2015','3/10/2015');6 l* j+ I& K- G% e5 X' x
yhoo = array2table(array,...$ [3 r+ F% b& z% ]
'VariableNames', {'date','open','high','low','closing','volumn','adjusted'})( o, A8 T: h$ p1 Q
& `; c$ O( ?, y* ?8 ~第4行中,我们通过VariableName来指定表头的内容,结果显示如下
, ?3 S9 P; {6 ^, K
9 k5 e9 D) `( [$ s& H; U( I% yhoo的table在命令行的显示5 }5 I M) V4 A. U
yhoo =
* s& p8 g2 W" {5 m date open high low closing volumn adjusted: ?/ `2 M. C+ z W) Z
__________ _____ _____ _____ _______ __________ ________
* v2 l) c7 W" M 7.3603e+05 42.57 42.92 42.18 42.68 1.0601e+07 42.68
4 K2 O" L+ I9 W3 P 7.3603e+05 43.6 43.93 42.67 42.98 1.1802e+07 42.98
* @ E4 f7 P$ n/ r# H! ~" O 7.3603e+05 43.98 44.24 43.4 43.44 1.1888e+07 43.44 # ^4 l, W; ^ i( t: y2 k
7.3603e+05 44.18 44.31 43.5 44.16 1.1868e+07 44.16 % ]/ r4 n6 r A% U, ]
7.3603e+05 42.08 44.38 41.97 43.99 3.0099e+07 43.99 % @9 b3 I8 b7 u% c+ Z" Q
7.3603e+05 43.7 43.95 42.42 42.62 2.2392e+07 42.62
" M0 E# K+ a; r, F" L# I1 z- L. x; G 7.3603e+05 44.06 44.43 43.7 44.11 1.1027e+07 44.11
! _: |& T- `* J2 m1 e0 B8 i
% a+ M& x/ J' w( E访问table中的数据
1 z8 }9 I- N" C3 q7 R2 L: R; y2 k3 A
6 J+ ^% O, `3 I& c, D" ~- e通过表Table.1所建立的table对象,在命令行中显示如下:
; b' d. ^! ~0 |- U5 U, b. ]9 u" {- ]& G
% nasdaq table在命令行中的显示
# N+ _" F7 j& U6 K5 |8 D/ Xnasdaq = 7 P ~4 \1 V, D9 b0 d# q% P
Symbol Name MarketCap IPOYear
3 S f% z6 T0 K" F8 E! {6 B6 [ ______ _______________________ __________ _______
- t8 E1 h6 v% S: ~6 j5 p6 m$ d3 k5 {9 @4 Y, f- d
'AAPL' 'Apple Inc' '$742.63B' 1980 - a; A1 Y* a- {9 s
'AMZN' 'Amazon.com Inc' '$173.33B' 1997 . V0 U" m5 D& O' {7 c0 u
'MSFT' 'Microsoft Corporation' '$346.9B' 1986 + @, f# b, Z0 B" D L! z( D# S
8 ]5 B/ Q% s+ L0 I Q& u, ~# G
我们可以通过使用dot+Variablename的语法直接访问table中的列,返回的结果是cell格式的数据:$ ^% M* k5 _8 p# @3 u; t Q
& Q7 g7 }# ^$ q8 |, ~2 x% W% 使用dot语法访问table中的数据7 o% I4 d' D, c% g* b
>> nasdaq.Symbol % dot格式+变量名的访问方式
' y+ G# t9 w+ i( fans =
+ p3 a# ?! @! M/ J) |6 V. T 'AAPL'
, z( p+ B" R; ]; y. Y 'AMZN' s* X) J% q1 _6 G, r8 p
'MSFT'
; Y( L9 r( K0 D2 h. B>> class(nasdaq) % 返回cell格式的数据- q4 Q( D; g, C; d# }
ans =" T k, R! t- I9 j. R/ Y
cell $ @1 ^( E+ K8 g9 u6 L& o
$ T: }" c0 R! y/ u8 u1 }
table类重载了subsref函数(什么是运算符的重载,参加《MATLAB面向对象编程-从入门到设计模式》12.1节),于是支持MATLAB传统的圆括号下标访问,如果要访问第一行,则:: z F# t, [8 ^, i( }
: z p' X0 x5 T4 i) x% 使用下标语法访问table中的数据
0 j1 ]2 s. @/ p o6 i1 V) O>> nasdaq(1,:)
4 S! ^" r1 D& mans =
' p$ D; {: x o$ B$ X Symbol Name MarketCap IPOYear
* K# E8 |0 o7 }" Y5 H' I( z6 W ______ ___________ __________ _______- @- p+ d% z I' s: ?! T/ g
# r/ Q' |3 m8 v, Z 'AAPL' 'Apple Inc' '$742.63B' 1980
0 v: j7 K" B, }* S2 |2 @6 U6 a& @4 N3 e4 L, g7 j
使用圆括号,返回的结果仍然是table,如果要访问第2到3行,则:
0 g1 }) q) G% T6 F3 P1 P$ R
. s! \: z9 F9 W+ p# _8 C; O- Y, F% 使用下标语法访问table中的数据
6 {# m6 o$ R, C- k$ j$ j>> nasdaq(2:3,:)" y, F4 v7 ]* r: y
ans =
" S& v' q1 B( E1 B4 h& `' t Symbol Name MarketCap IPOYear
% j1 d) B( j* l4 t) w ______ _______________________ __________ _______% f. l$ B+ v Q2 L: g; E5 @& N
3 f9 Q: U& A' L. I6 Z* `
'AMZN' 'Amazon.com Inc' '$173.33B' 1997
& e( Y9 a# _2 t 'MSFT' 'Microsoft Corporation' '$346.9B' 1986
- D1 J9 l! c/ h; r
$ I9 M2 t% _* G, p返回的结果仍然是table。 table数据结构支持MATLAB传统的花括号下标访问,返回的结果是cell格式的数据
3 F) \. g. {' y9 s* O) m1 O* \
1 N1 H% N8 [1 T5 Y. [0 ]% 花括号下标访问
' @4 f( M* M* |. X9 p8 o( H2 G>> nasdaq{:,1} % 花括号下标访问,返回第一列中的数据' @9 O( A$ Z# h7 l6 c* n
ans = 1 n2 e/ |% }7 \' d3 l# {
'AAPL': Y8 }3 @2 S9 g
'AMZN'
0 c- ~& e5 \0 `: t 'MSFT' ! X/ }. h: M% j
5 o' }# @+ r+ g9 ~0 p还可以把Dot语法和下标语法结合起来获取数据,下例代码访问table第一列的第三行,返回的结果是元胞。
% z Q* k' j: |9 W, m: X6 i! N
0 i" D8 \, Q0 T6 o% Dot语法和圆括号下标访问结合8 G# I5 X+ D1 J$ Q! N
>> nasdaq.Symbol(3)7 v' e3 B5 O. V6 F' m7 D6 J
ans =
4 {* M, O8 O, _3 V 'MSFT'
) |( B5 d! C% J" X8 i6 y>> class(ans) % 圆括号下标访问,返回结果是元胞 / ^# s+ L1 Z- z% H' a
ans =
6 Z; j/ W) A3 Q; |cell
4 H4 l7 f" S; c, [5 X |
|