将带有字典对象的pandas Dataframe 转换为带有对象类型的polars Dataframe

pxiryf3j  于 2023-03-28  发布在  其他
关注(0)|答案(1)|浏览(260)

我有一个带有一列字典的pandas Dataframe 。我想将其转换为dtype为polars.Object的polars Dataframe ,它显然 Package 了任意Python对象。我无法弄清楚如何做到这一点。
请看下面的代码:

>>> df = pandas.DataFrame({ "the_column": [{ "key" : 123 }, { "foo" : 456 }, { "bar" : 789 }]})
>>> df
     the_column
0  {'key': 123}
1  {'foo': 456}
2  {'bar': 789}
>>> polars.from_pandas(df)
shape: (3, 1)
┌─────────────────┐
│ the_column      │
│ ---             │
│ struct[3]       │
╞═════════════════╡
│ {null,null,123} │
│ {null,456,null} │
│ {789,null,null} │
└─────────────────┘

正如你所看到的,默认情况下,polars会尝试将字典转换为箭头结构体。这不是我想要的,因为每个对象的键都不一样。我希望它们保持为Python对象。schema_overrides功能做了一些事情,但也不是我想要的:

>>> polars.from_pandas(df, schema_overrides = {'the_column': polars.Object })
thread '<unnamed>' panicked at 'cannot convert object to arrow', /Users/runner/work/polars/polars/polars/polars-core/src/datatypes/dtype.rs:232:26
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/homebrew/lib/python3.10/site-packages/polars/utils.py", line 498, in wrapper
  File "/opt/homebrew/lib/python3.10/site-packages/polars/utils.py", line 433, in wrapper
  File "/opt/homebrew/lib/python3.10/site-packages/polars/convert.py", line 486, in from_pandas
    include_index=include_index,
  File "/opt/homebrew/lib/python3.10/site-packages/polars/utils.py", line 433, in wrapper
  File "/opt/homebrew/lib/python3.10/site-packages/polars/internals/dataframe/frame.py", line 642, in _from_pandas
  File "/opt/homebrew/lib/python3.10/site-packages/polars/utils.py", line 433, in wrapper
  File "/opt/homebrew/lib/python3.10/site-packages/polars/internals/construction.py", line 1410, in pandas_to_pydf
  File "/opt/homebrew/lib/python3.10/site-packages/polars/internals/construction.py", line 1242, in arrow_to_pydf
    schema, schema_overrides=schema_overrides
  File "/opt/homebrew/lib/python3.10/site-packages/polars/internals/construction.py", line 577, in _post_apply_columns
    column_names,  # type: ignore[return-value]
pyo3_runtime.PanicException: cannot convert object to arrow

我怎么能在这里实现我想要的呢?

sczxawaw

sczxawaw1#

简短回答

你不知道。

更长的答案

如书中所述,Object数据的支持有限。在这里,你遇到了其中的一个限制,因为python字典的集合不是Arrow标准中的数据类型,至少在没有大量定制的情况下是这样。此外,对于python字典的列,无论如何你不能以高性能的方式“处理”数据。
如果你想使用polars(你应该使用它,它非常酷!),那么我建议你最好简单地将数据重新构造为一种格式,这种格式能够很好地使用polars将处理的(基于列的)Arrow数据结构。
例如,在你的例子中,每个python dict中只有一个键值对。让我们假设这总是为真,那么你可以创建包含键的列"key",以及另一个包含值的列"value"。这两个结构之间的信息损失完全为零,但是在建议的两列版本中,你现在可以对结果帧做任何你喜欢的事情。

(
    pl.DataFrame(
        {
            "the_column": pl.Series(
                [
                    {"key": 123},
                    {"foo": 456},
                    {"bar": 789},
                ],
                dtype=pl.Object
            ),
        }
    )
    .select(
        pl.col("the_column")
        .apply(lambda x: list(x.keys()))
        .arr.get(0)
        .alias("key"),
        pl.col("the_column")
        .apply(lambda x: list(x.values()))
        .arr.get(0)
        .alias("value"),
    )
)

shape: (3, 2)
┌─────┬───────┐
│ key ┆ value │
│ --- ┆ ---   │
│ str ┆ i64   │
╞═════╪═══════╡
│ key ┆ 123   │
│ foo ┆ 456   │
│ bar ┆ 789   │
└─────┴───────┘

或者类似的东西,这取决于你的实际数据是什么样子的。

相关问题