如何将 Pydantic BaseModel 列表转换为 Pandas 数据框

28

我似乎找不到任何内置方法来简单地将Pydantic BaseModel列表转换为Pandas Dataframe。

from pydantic import BaseModel
import pandas as pd

class SomeModel(BaseModel):
    col1: str
    col2: str

data = [SomeModel(**{'col1': 'foo', 'col2': 'bar'})] * 10
pd.DataFrame(data)

输出

>>         0            1
>> 0  (col1, foo)  (col2, bar)
>> 1  (col1, foo)  (col2, bar)
>> ...

通过这种方式,列被加载为数据。一种解决方法是执行以下操作:

pd.DataFrame([model.dict() for model in data])

输出

>>    col1 col2
>> 0  foo  bar
>> 1  foo  bar
>> ...

但是对于更大的数据量来说,这种方法有点慢。是否有更快的方式?

2个回答

28
一个快速而简单的性能分析得出以下数值:

from pydantic import BaseModel
import pandas as pd
from fastapi.encoders import jsonable_encoder
class SomeModel(BaseModel):
    col1: int
    col2: str

data = [SomeModel(col1=1,col2="foo"),SomeModel(col1=2,col2="bar")]*4*10**5

import cProfile

cProfile.run( 'pd.DataFrame([s.dict() for s in data])' ) # around 8.2s
cProfile.run( 'pd.DataFrame(jsonable_encoder(data))' ) # around 30.8s
cProfile.run( 'pd.DataFrame([s.__dict__ for s in data])' ) # around 1.7s
cProfile.run( 'pd.DataFrame([dict(s) for s in data])' ) # around 3s

能否将 vars(s) 添加到比较中(如果在性能上相同,它应该是更具 Python 风格的替代方案,而不是 s.__dict__)? - Dev-iL

12

不确定速度是否更快,但FastAPI公开了jsonable_encoder,它基本上对任意嵌套的BaseModel结构执行相同的转换:

from fastapi.encoders import jsonable_encoder
pd.DataFrame(jsonable_encoder(data))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接