数组向量(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]