TableAppender
由于 Python 与 DolphinDB 的数据类型并不是一一对应的,故部分类型数据无法直接进行上传、写入等操作。举例来说,Python 中的 DataFrame 对象中仅支持 datetime64[ns] 时间类型,若直接从 API 上传 DataFrame 数据到 DolphinDB,所有的时间类型列均将转换为 NANOTIMESTAMP 类型。并且每次向内存表或分布式表追加一个带有时间类型列的 DataFrame 时,用户需要专门对时间列进行类型转换,该类情况影响了用户的使用体验。
针对以上情况,Python API 提供了 TableAppender 对象,在通过 append
方法向内存表或者分布式表中添加本地 DataFrame 数据时,能够实现对部分类型进行自动转换,用户无须再进行额外的手动转换。
注意:
- 1.30.19.4及之前版本的 API 仅支持使用
TableAppender
对时间类型数据进行自动转换;1.30.21.1及之后版本的 API 支持使用TableAppender
对所有类型数据的自动转换。 - 1.30.16、2.00.4及之后版本的 DolphinDB 支持使用 tableInsert 对时间类型数据进行自动转换。
- 1.30.22.1及之后版本的 API,调整 tableAppender 类名为 TableAppender,兼容原有 tableAppender。
接口说明
TableAppender(dbPath=None, tableName=None, ddbSession=None, action="fitColumnType")
- dbPath :分布式数据库的地址。若待写入表为内存表,可以不指定该参数。
- tableName :分布式表或内存表的表名。
- ddbSession :已连接 DolphinDB 的 session 对象。
- action :指定 append 表时的行为。目前仅支持 fitColumnType,表示对列类型进行转换。
TableAppender 类仅支持append
方法,接口如下:
append(table)
- table :待写入数据,通常为 pandas.DataFrame 类型的本地数据。
该方法返回一个整数,表示追加的记录条数。
示例
下例创建了一个共享表 t,通过 TableAppender
向表 t 中添加数据。
import pandas as pd import dolphindb as ddb import numpy as np s = ddb.session() s.connect("localhost", 8848, "admin", "123456") s.run("share table(1000:0, `sym`timestamp`qty, [SYMBOL, TIMESTAMP, INT]) as t") appender = ddb.TableAppender(tableName="t", ddbSession=s) data = pd.DataFrame({ 'sym': ['A1', 'A2', 'A3', 'A4', 'A5'], 'timestamp': np.array(['2012-06-13 13:30:10.008', 'NaT','2012-06-13 13:30:10.008', '2012-06-13 15:30:10.008', 'NaT'], dtype="datetime64[ms]"), 'qty': np.arange(1, 6).astype("int32"), }) num = appender.append(data) print("append rows: ", num) t = s.run("t") print(t) schema = s.run("schema(t)") print(schema["colDefs"])
输出结果如下:
append rows: 5
sym timestamp qty
0 A1 2012-06-13 13:30:10.008 1
1 A2 NaT 2
2 A3 2012-06-13 13:30:10.008 3
3 A4 2012-06-13 15:30:10.008 4
4 A5 NaT 5
name typeString typeInt extra comment
0 sym SYMBOL 17 NaN
1 timestamp TIMESTAMP 12 NaN
2 qty INT 4 NaN
共享表 t 中的 timestamp 列被定义为 TIMESTAMP 类型,但是在 API 端写入的 pd.DataFrame 对象中该列的数据类型对应为 datetime64[ns]。由上述结果可知,通过 TableAppender
将表 t 从 API 上传至 DolphinDB 后,该列的数据类型将自动转换为TIMESTAMP。
常见问题
自动转换的类型
1.30.16、2.00.4 之后版本的 DolphinDB 支持向内存表写入数据时自动转换时间类型,因此用户可以不使用本文介绍的 TableAppender
方法,而是使用 run 方法执行 tableInsert
将上传的 DataFrame 本地时间类型数据插入到指定表中。
此外,由于在 Python API 中 DolphinDB 的 UUID、INT128、IPADDR、BLOB 等类型对应 Python 的 str 类型,故无法直接上传这些类型的数据,进而无法插入到指定表中。在 1.30.19.4 及之后版本的 Python API 中,TableAppender 对象支持自动识别指定表的类型,如果上传数据中包含 UUID 等特殊类型,TableAppender 对象将自动识别 str 类型,并将其转换为表中对应的类型。写入数据时的类型转换相关内容,请参考章节类型转换。
简单示例如下:
import dolphindb as ddb import dolphindb.settings as keys import numpy as np import pandas as pd s = ddb.session(protocol=keys.PROTOCOL_DDB) s.connect("192.168.1.113", 8848, "admin", "123456") s.run("share table(1000:0, `sym`uuid`int128`ipaddr`blob, [SYMBOL, UUID, INT128, IPADDR, BLOB]) as t") appender = ddb.TableAppender(tableName="t", ddbSession=s) data = pd.DataFrame({ 'sym': ["A1", "A2", "A3"], 'uuid': ["5d212a78-cc48-e3b1-4235-b4d91473ee87", "b93b8253-8d5e-c609-260a-86522b99864e", ""], 'int128': [None, "073dc3bc505dd1643d11a4ac4271d2f2", "e60c84f21b6149959bcf0bd6b509ff6a"], 'ipaddr': ["2c24:d056:2f77:62c0:c48d:6782:e50:6ad2", "", "192.168.1.0"], 'blob': ["testBLOB1", "testBLOB2", "testBLOB3"], }) appender.append(data) t = s.run("t") print(t)
注: 上例中,由于要下载并展示 BLOB 类型的数据,而 session 默认的数据传输协议 PROTOCOL_PICKLE 并不支持 BLOB 类型数据,故须指定其数据传输协议为 PROTOCOL_DDB。
输出结果如下:
sym uuid int128 ipaddr blob
0 A1 5d212a78-cc48-e3b1-4235-b4d91473ee87 00000000000000000000000000000000 2c24:d056:2f77:62c0:c48d:6782:e50:6ad2 testBLOB1
1 A2 b93b8253-8d5e-c609-260a-86522b99864e 073dc3bc505dd1643d11a4ac4271d2f2 0.0.0.0 testBLOB2
2 A3 00000000-0000-0000-0000-000000000000 e60c84f21b6149959bcf0bd6b509ff6a 192.168.1.0 testBLOB3
Pandas 警告
在 1.30.19.4 及之后版本的 Python API 中,用户在使用 TableAppender 类的 append
方法写入数据时,可能会收到如下警告:
UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
该警告并不会对程序执行造成任何影响,如需屏蔽,可以使用如下方法:
import warnings warnings.filterwarnings("ignore","Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access", UserWarning)