与 pandas 进行交互
DuckDB 与 Python 生态的pandas 提供了交互,即运行直接在 DataFrame 上进行 SQL 查询。
Python
import duckdb
import pandas
# Create a Pandas dataframe
my_df = pandas.DataFrame.from_dict({"a": [42]})
# query the Pandas DataFrame "my_df"
# Note: duckdb.sql connects to the default in-memory database connection
duckdb.sql("SELECT * FROM my_df").df()
a
------
0 42
从 DataFrame 导入
DataFrame 可以直接作为虚拟视图在 SQL 语句中使用:
Python
import duckdb
import pandas
# Create a Pandas dataframe
my_df = pandas.DataFrame.from_dict({"a": [42]})
# 创建表的同时插入数据
duckdb.sql("CREATE TABLE my_table AS SELECT * FROM my_df")
# 已存在表可以直接插入
duckdb.sql("INSERT INTO my_table SELECT * FROM my_df")
# 如果列的顺序不同或并非所有列都存在于 DataFrame 可以使用
duckdb.sql("INSERT INTO my_table BY NAME SELECT * FROM my_df")
导出数据到 DataFrame 中
有两个方法来将结果转换为 DataFrame:
df()/fetchdf()/fetch_df()
: 将结果表转换为 DataFrame 对象fetch_df_chunk(vector_multiple=1)
: 将部分结果提取到 DataFrame 中,每个块中返回2048 * vector_multiple
行,返回的结果行并不一定是 2048*vector_multiple
Python
# 没有实现迭代器接口必须手动循环
result = duckdb.cursor().execute("SELECT * FROM range(10) as rel(id)")
while True:
temp_df = result.fetch_df_chunk(10)
if len(temp_df) == 0:
break
fetch_df_chunk 的使用逻辑和迭代器完全不一样,默认情况下使用的内存并不会被回收,因此一个非常大的数据库执行 fetch_df_chunk 操作会占用大量的内存。此时就必须指定 set memory_limit ='20G'
这样的来限制内存使用量。
用于 Relational API
DataFrame 在 DuckDB 中直接被认为是一个虚拟表,但是我们只能将它作为右表使用,而无法直接作为左表使用。此时我们就需要通过方法来将它封装为 DuckDBPyRelation 对象:
Python
import duckdb
import pandas
input_df = pandas.DataFrame.from_dict(
{"i": [1, 2, 3, 4], "j": ["one", "two", "three", "four"]}
)
# 是直接可以作为右表使用的
duckdb.sql("SELECT * FROM input_df")
# 从 DataFrame 来构造 DuckDBPyRelation 对象来作为左表
rel = duckdb.from_df(input_df)
# 此时就可以作为左表使用了
rel.filter("i >= 2").project("i, j, i*2 as two_i").order("i desc").limit(2).show()
┌───────┬─────────┬───────┐
│ i │ j │ two_i │
│ int64 │ varchar │ int64 │
├───────┼─────────┼───────┤
│ 4 │ four │ 8 │
│ 3 │ three │ 6 │
└───────┴─────────┴───────┘