本页面记录了将Python对象转换为DuckDB以及将DuckDB结果转换为Python的规则。
对象转换:Python 对象到 DuckDB
这是Python对象类型到DuckDB 逻辑类型的映射:
None→NULLbool→BOOLEANdatetime.timedelta→INTERVALstr→VARCHARbytearray→BLOBmemoryview→BLOBdecimal.Decimal→DECIMAL/DOUBLEuuid.UUID→UUID
其余的转换规则如下。
int
由于在Python中整数可以是任意大小的,因此对于整数来说没有一对一的转换可能。 相反,我们按顺序执行这些转换,直到其中一个成功:
BIGINTINTEGERUBIGINTUINTEGERDOUBLE
使用DuckDB Value类时,可以设置目标类型,这将影响转换。
float
这些转换按顺序尝试,直到一个成功:
DOUBLEFLOAT
datetime.datetime
对于datetime,我们将检查pandas.isnull是否可用,如果返回true,则返回NULL。
我们检查datetime.datetime.min和datetime.datetime.max以分别转换为-inf和+inf。
如果 datetime 有 tzinfo,我们将使用 TIMESTAMPTZ,否则它将变为 TIMESTAMP。
datetime.time
如果time有tzinfo,我们将使用TIMETZ,否则它将变为TIME。
datetime.date
date 转换为 DATE 类型。
我们检查 datetime.date.min 和 datetime.date.max 以分别转换为 -inf 和 +inf。
bytes
bytes 默认转换为 BLOB,当它用于构造类型为 BITSTRING 的 Value 对象时,它映射到 BITSTRING。
list
list 成为其子元素“最宽松”类型的 LIST 类型,例如:
my_list_value = [
12345,
"test"
]
将变为 VARCHAR[] 因为 12345 可以转换为 VARCHAR 但 test 不能转换为 INTEGER。
[12345, test]
dict
dict 对象可以根据其结构转换为 STRUCT(...) 或 MAP(..., ...)。
如果字典的结构类似于:
my_map_dict = {
"key": [
1, 2, 3
],
"value": [
"one", "two", "three"
]
}
然后我们将它转换为两个列表压缩在一起的键值对的MAP。
上面的例子变成了一个MAP(INTEGER, VARCHAR):
{1=one, 2=two, 3=three}
字段的名称很重要,两个列表需要具有相同的大小。
否则我们将尝试将其转换为STRUCT。
my_struct_dict = {
1: "one",
"2": 2,
"three": [1, 2, 3],
False: True
}
变为:
{'1': one, '2': 2, 'three': [1, 2, 3], 'False': true}
字典的每个
key都被转换为字符串。
tuple
tuple 默认转换为 LIST,当它用于构造类型为 STRUCT 的 Value 对象时,它将转换为 STRUCT。
numpy.ndarray 和 numpy.datetime64
ndarray 和 datetime64 通过调用 tolist() 并转换其结果来进行转换。
结果转换:DuckDB 结果到 Python
DuckDB的Python客户端提供了多种额外的方法,可以用于高效地检索数据。
NumPy
fetchnumpy()将数据作为NumPy数组的字典获取
Pandas
df()将数据作为 Pandas DataFrame 获取fetchdf()是df()的别名fetch_df()是df()的别名fetch_df_chunk(vector_multiple)将部分结果提取到DataFrame中。每个块返回的行数是向量大小(默认为2048)乘以vector_multiple(默认为1)。
Apache Arrow
arrow()将数据作为 Arrow 表 获取fetch_arrow_table()是arrow()的别名fetch_record_batch(chunk_size)返回一个 Arrow 记录批次读取器,每批次包含chunk_size行
Polars
pl()将数据获取为 Polars DataFrame
Examples
以下是一些使用此功能的示例。更多示例请参见Python指南。
获取为Pandas DataFrame:
df = con.execute("SELECT * FROM items").fetchdf()
print(df)
item value count
0 jeans 20.0 1
1 hammer 42.2 2
2 laptop 2000.0 1
3 chainsaw 500.0 10
4 iphone 300.0 2
以NumPy数组的字典形式获取:
arr = con.execute("SELECT * FROM items").fetchnumpy()
print(arr)
{'item': masked_array(data=['jeans', 'hammer', 'laptop', 'chainsaw', 'iphone'],
mask=[False, False, False, False, False],
fill_value='?',
dtype=object), 'value': masked_array(data=[20.0, 42.2, 2000.0, 500.0, 300.0],
mask=[False, False, False, False, False],
fill_value=1e+20), 'count': masked_array(data=[1, 2, 1, 10, 2],
mask=[False, False, False, False, False],
fill_value=999999,
dtype=int32)}
获取为Arrow表。之后转换为Pandas仅用于美观打印:
tbl = con.execute("SELECT * FROM items").fetch_arrow_table()
print(tbl.to_pandas())
item value count
0 jeans 20.00 1
1 hammer 42.20 2
2 laptop 2000.00 1
3 chainsaw 500.00 10
4 iphone 300.00 2