数组向量(array vector)
New in version 2.00.2.
DolphinDB中的数组向量 (array vector) 是一种特殊的向量,用于存储可变长度的二维数组。数据表通常将数据类型相同且含义相近的多列存为一列,例如股票的多档报价数据。这种存储方式可显著简化某些常用的查询与计算。若不同列中含有大量重复数据,使用数组向量存储亦可提高数据压缩比,提升查询速度。
数组向量可以与标量、向量或另一个数组向量进行二元运算。
目前,仅内存表与使用 TSDB 存储引擎的分布式表支持数组向量,OLAP 存储引擎暂不支持数组向量。数组向量类型的列不可用作分布式表的分区字段或排序字段。
创建数组向量
使用 array 函数或 bigarray 函数初始化生成空的数组向量。 请注意,指定数据类型时,需在数据类型后添加“[]”,以表示创建数组向量,且 initialSize 必须为 0。
目前支持以下数据类别:Logical, Integral(不包括 INT128, COMPRESS 类型), Floating, DECIMAL, Temporal。
向量和数组向量的相互转化
向量转数组向量:
(1)通过 arrayVector 将单个向量转换成数组向量。
(2)通过 fixedLengthArrayVector 将多个向量拼接成数组向量。
数组向量转向量:
通过 flatten 将数组向量转换成向量。
$ a=array(INT[], 0, 10).append!([1 2 3, 4 5, 6 7 8, 9 10]);
$ a
[[1,2,3],[4,5],[6,7,8],[9,10]]
$ flatten(a)
[1,2,3,4,5,6,7,8,9,10]
数组向量转化为矩阵
通过函数 matrix 可以将每个元素等长的数组向量转换成矩阵,以进一步进行矩阵计算。
$ bid = array(DOUBLE[], 0, 20).append!([1.4799 1.479 1.4787 1.4784 1.4667, 1.4796 1.479 1.4782 1.4781 1.4783, 1.4791 1.479 1.4785 1.4698 1.4720, 1.4699 1.469 1.4707 1.4704 1.4697, 1.4789 1.477 1.4780 1.4724 1.4669])
$ ask = array(DOUBLE[], 0, 20).append!([1.4821 1.4825 1.4828 1.4900 1.4792, 1.4818 1.482 1.4821 1.4818 1.4829, 1.4814 1.4818 1.482 1.4825 1.4823, 1.4891 1.4885 1.4898 1.4901 1.4799, 1.4811 1.4815 1.4818 1.4800 1.4799])
$ TradeDate = 2022.01.01 + 1..5
$ SecurityID = rand(`APPL`AMZN`IBM, 5)
$ t = table(SecurityID as `sid, TradeDate as `date, bid as `bid, ask as `ask)
$ result = select toArray(matrix(bid).corrMatrix()) as corr_bid, toArray(matrix(ask).corrMatrix()) as corr_ask from t group by sid
$ corrMatrix_bid = result.corr_bid.matrix().avg().reshape(5:5)
$ corrMatrix_ask = result.corr_ask.matrix().avg().reshape(5:5)
$ corrMatrix_bid;
col1 |
col2 |
col3 |
col4 |
col5 |
---|---|---|---|---|
1 |
0.9995 |
0.9984 |
0.7417 |
(0.1308) |
0.9995 |
1 |
0.9997 |
0.7214 |
(0.1466) |
0.9984 |
0.9997 |
1 |
0.7061 |
(0.1589) |
0.7417 |
0.7214 |
0.7061 |
1 |
(0.0264) |
(0.1308) |
(0.1466) |
(0.1589) |
(0.0264) |
1 |
$ corrMatrix_ask;
col1 |
col2 |
col3 |
col4 |
col5 |
---|---|---|---|---|
1 |
0.9999 |
0.9997 |
0.9963 |
(0.9861) |
0.9999 |
1 |
0.9999 |
0.9974 |
(0.9883) |
0.9997 |
0.9999 |
1 |
0.9981 |
(0.9899) |
0.9963 |
0.9974 |
0.9981 |
1 |
(0.9968) |
(0.9861) |
(0.9883) |
(0.9899) |
(0.9968) |
1 |
向数组向量中插入数据
只支持使用 append! 方法向数组向量中插入标量、元组或数组向量。暂不支持对数组向量的更新和删除操作。
// 插入scalar
$ a=array(DOUBLE[], 0, 10).append!(2.5);
$ print a;
[[2.5]]]
// 插入tuple
$ a=array(DATE[], 0, 10).append!((2021.10.15, 2021.10.16, 2021.10.17));
$ print a;
[[2021.10.15],[2021.10.16],[2021.10.17]]
// 插入数组向量
$ a=array(INT[], 0, 10).append!([1 2 3, 4 5, 6 7 8, 9 10]);
$ print a;
[[1,2,3],[4,5],[6,7,8],[9,10]]
读取数组向量中的数据
数组向量
$ av =array(DOUBLE[], 0, 10).append!([1.0, 2.1 4.1 6.8, 0.5 2.2 2]);
$ print av
[[1],[2.1,4.1,6.8],[0.5,2.2,2]]
$ typestr(av)
FAST DOUBLE[] VECTOR
元组
$ tp = [[1],[2.1,4.1,6.8],[0.5,2.2,2]]
$ typestr(tp)
ANY VECTOR
由上述例子可以看出,数组向量和元组的打印(print)形式一致。但两者读取数据的方式不完全相同。
相同点:
都可以通过 row 读取行数据。
不同点:
数组向量的下标只能表示列索引,可以通过列索引(从0开始)读取一列数据,如 “av[index]”。若要读取某行数据,需通过 row 函数读取,如 “av.row(index)“。如需定位到某个具体的数据,可以先定位到列,再定位行,如 “av[index1][index2]”;或先定位行,如:av.row(index1)[index2]。
$ av[1]
[,4.1,2.2]
$ tp[,1]
(,4.1,2.2)
$ av.row(1)
[2.1,4.1,6.8]
$ tp[1]
[2.1,4.1,6.8]
导入表时存储为数组向量(2.00.4 及以上版本)
目前暂不支持导入时将文本文件的多列数据存成 DolphinDB 数据表的一列。如需导入数组向量,可以在导入前,将文本文件的多列数据合并存储到一列中,并通过特定的标识符分隔多列数据,如对于五档报价的一行数据可以在一列中存储为 “1.4799|1.479|1.4787|1.4796|1.479” 。
使用 loadText (ploadText) 与 loadTextEx 导入数据时,通过参数 arrayDelimiter 指定分隔符(上述报价数据分隔符是 “|”),即可在导入数据表时将该列的识别为数组向量。
注意:导入数据前需在 schema 中修改数组向量对应列的类型。
$ bid = array(DOUBLE[], 0, 20).append!([1.4799 1.479 1.4787, 1.4796 1.479 1.4784, 1.4791 1.479 1.4784])
$ ask = array(DOUBLE[], 0, 20).append!([1.4821 1.4825 1.4828, 1.4818 1.482 1.4821, 1.4814 1.4818 1.482])
$ TradeDate = 2022.01.01 + 1..3
$ SecurityID = rand(`APPL`AMZN`IBM, 3)
$ t = table(SecurityID as `sid, TradeDate as `date, bid as `bid, ask as `ask)
$ t;
$ saveText(t,filename="/home/t.csv",delimiter=',',append=true)
$ path = "/home/t.csv"
$ schema=extractTextSchema(path);
$ update schema set type = "DOUBLE[]" where name="bid" or name ="ask"
$ t = loadText(path, schema=schema, arrayDelimiter=",")
$ t;
sid |
date |
bid |
ask |
---|---|---|---|
AMZN |
2022.01.02 |
[1.4799,1.479,1.4787] |
[1.4821,1.4825,1.4828] |
AMZN |
2022.01.03 |
[1.4796,1.479,1.4784] |
[1.4818,1.482,1.4821] |
IBM |
2022.01.04 |
[1.4791,1.479,1.4784] |
[1.4814,1.4818,1.482] |
将表的多列合并成一个数组向量
通过函数 fixedLengthArrayVector 将表的多列数据存成一列。
$ syms="A"+string(1..30)
$ datetimes=2019.01.01T00:00:00..2019.01.31T23:59:59
$ n=200
$ if(existsDatabase("dfs://stock")) {
$ dropDatabase("dfs://stock")
$ }
$ db=database("dfs://stock",RANGE,cutPoints(syms,3));
$ t=table(take(datetimes,n) as trade_time, take(syms,n) as sym,take(500+rand(10.0,n), n) as bid1, take(500+rand(20.0,n),n) as bid2)
$ quotes=db.createPartitionedTable(t,`quotes,`sym).append!(t)
$ t1=select sym, fixedLengthArrayVector(bid1,bid2) as bid from quotes
将表分组数据聚合成一个数组向量
DolphinDB 提供了函数 toArray 搭配 group by 语句使用。toArray 可以将 group by 分组的数据存储成数组向量的一行,便于用户直接查看该分组下的所有数据。
$ ticker = `AAPL`IBM`IBM`AAPL`AMZN`AAPL`AMZN`IBM`AMZN
$ volume = 106 115 121 90 130 150 145 123 155;
$ t = table(ticker, volume);
$ t;
$ t1 = select toArray(volume) as volume_all from t group by ticker;
$ t1;
ticker |
volume_all |
---|---|
AAPL |
[106,90,150] |
AMZN |
[130,145,155] |
IBM |
[115,121,123] |
数组向量按行计算
(1) 聚合计算
支持 row 系列函数,如 rowMax, rowStd 等;支持调用高阶函数 byRow,对数组向量的每行元素进行聚合计算。
$ a=array(DOUBLE[], 0, 10).append!([8.3 1.2 5.6, 1.8 3.3, 0.1 2.4 6.8]);
$ rowMax(a);
[8.3, 3.3, 6.7]
$ bid = array(DOUBLE[], 0, 20).append!([1.4799 1.479 1.4787, 1.4796 1.479 1.4784, 1.4791 1.479 1.4784])
$ ask = array(DOUBLE[], 0, 20).append!([1.4821 1.4825 1.4828, 1.4818 1.482 1.4821, 1.4814 1.4818 1.482])
$ TradeDate = 2022.01.01 + 1..3
$ SecurityID = rand(`APPL`AMZN`IBM, 3)
$ t = table(SecurityID as `sid, TradeDate as `date, bid as `bid, ask as `ask)
$ t;
sid |
date |
bid |
ask |
---|---|---|---|
IBM |
2022.01.02 |
[1.4799,1.479,1.4787] |
[1.4821,1.4825,1.4828] |
APPL |
2022.01.03 |
[1.4796,1.479,1.4784] |
[1.4818,1.482,1.4821] |
APPL |
2022.01.04 |
[1.4791,1.479,1.4784] |
[1.4814,1.4818,1.482] |
$ select SecurityID, TradeDate, bid, ask, rowAvg(bid) as bid_avg, rowAvg(ask) as ask_avg from t
SecurityID |
TradeDate |
bid |
ask |
bid_avg |
ask_avg |
---|---|---|---|---|---|
IBM |
2022.01.02 |
[1.4799,1.479,1.4787] |
[1.4821,1.4825,1.4828] |
1.4792 |
1.4825 |
APPL |
2022.01.03 |
[1.4796,1.479,1.4784] |
[1.4818,1.482,1.4821] |
1.479 |
1.482 |
APPL |
2022.01.04 |
[1.4791,1.479,1.4784] |
[1.4814,1.4818,1.482] |
1.4788 |
1.4817 |
(2) 窗口计算(滑动窗口、累计窗口等)
通过高阶函数 byRow 将窗口计算应用在数组向量的每行元素上。
$ select SecurityID, TradeDate, bid, ask, byRow(cumavg, bid) as bid_cum, byRow(cumavg, ask) as ask_cum from t
SecurityID |
TradeDate |
bid |
ask |
bid_cum |
ask_cum |
---|---|---|---|---|---|
IBM |
2022.01.02 |
[1.4799,1.479,1.4787] |
[1.4821,1.4825,1.4828] |
[1.4799,1.47945,1.4792] |
[1.4821,1.4823,1.482467] |
APPL |
2022.01.03 |
[1.4796,1.479,1.4784] |
[1.4818,1.482,1.4821] |
[1.4796,1.4793,1.479] |
[1.4818,1.4819,1.481967] |
APPL |
2022.01.04 |
[1.4791,1.479,1.4784] |
[1.4814,1.4818,1.482] |
[1.4791,1.47905,1.478833] |
[1.4814,1.4816,1.481733] |