如何将列表列表转换为具有 list[struct[n]] 类型列的极坐标数据帧?

How to convert a list of lists into a polars dataframe with a column of type list[struct[n]]?

提问人:vinnewbie 提问时间:11/18/2023 最后编辑:vinnewbie 更新时间:11/19/2023 访问量:61

问:

我有一个列表列表。每个单独的列表可能具有不同的长度。列表的每个元素都是元组。

list1 = [("a", 1), ("b", 2)]
list2 = [("c", 3), ("d", 4), ("e", 5)]

我想将它们全部组合到一个类型为 list[struct[2]] 的极性数据帧列中。

在打印数据帧时,我应该看到:

    column_name

    list[struct[2]]

    [{"a",1}, {"b",2}]
    [{"c",3}, {"d",4}, {"e",5}]

我所要做的就是使用下面的代码获取一列 struct[2]

    list1 = ["a", "b", "c"]
    list2 = [1, 2, 3]

    df = pl.DataFrame({
        "col1": list1,
        "col2": list2
    })

    print (df)
    dfs = df.select(pl.struct(pl.all()).alias("my_struct"))
    print(dfs)

但这远不是我想要实现的目标

解决: 我使用以下代码解决了这个问题。看起来在极地结构与普通 python 中的字典具有相同的含义。

list1 = [("a", 1), ("b", 2)]
list2 = [("c", 3), ("d", 4), ("e", 5)]
list_of_lists = [list1, list2]
lofl_as_structs = [[dict(f1=pair[0], f2=pair[1]) for pair in lst] for lst in list_of_lists]
df = pl.DataFrame({"column_name": lofl_as_structs})
print(df)

结果:

shape: (2, 1)
┌─────────────────────────────┐
│ column_name                 │
│ ---                         │
│ list[struct[2]]             │
╞═════════════════════════════╡
│ [{"a",1}, {"b",2}]          │
│ [{"c",3}, {"d",4}, {"e",5}] │
└─────────────────────────────┘

附加问题:

我希望能够通过指定如下模式来稍微不同地执行上述操作:

df = pl.DataFrame(lofl_as_structs,schema={'column_name': pl.List(pl.Struct([pl.Field('f1', pl.Utf8), pl.Field('f2', pl.Int64)]))})

这给出了错误:

    raise ShapeError("the row data does not match the number of columns")
polars.exceptions.ShapeError: the row data does not match the number of columns

有关在架构中更改哪些内容以消除此错误的任何线索。

数据帧 列表 元组 python-polars

评论

0赞 ignoring_gravity 11/18/2023
你的结构的键应该是什么?
0赞 vinnewbie 11/19/2023
钥匙可以是任何东西。正如您从我上面的解决方案中看到的那样,它们并不重要。但是现在我希望能够直接指定架构并使其工作。谢谢!!
1赞 jqurious 11/19/2023
您需要另一个才能将其解析为单个列,例如[]pl.DataFrame([lofl_as_structs], ...)

答:

2赞 ignoring_gravity 11/18/2023 #1

假设您希望您的密钥是 ,您可以执行以下操作:'0', '1', ...

pl.Series(
    [[{str(i): val for i, val in enumerate(j)} for j in lst] for lst in [list1, list2]]
)

这给了

Out[26]:
shape: (2,)
Series: '' [list[struct[2]]]
[
        [{"a",1}, {"b",2}]
        [{"c",3}, {"d",4}, {"e",5}]
]

3赞 jqurious 11/18/2023 #2

Polars 中的每列都有一个架构(“类型”)。

如果我们举个例子:{"a": 1}, {"b": 2}

df = pl.select(pl.concat_list(pl.struct(a=1), pl.struct(b=2)))
shape: (1, 1)
┌──────────────────────┐
│ a                    │
│ ---                  │
│ list[struct[2]]      │
╞══════════════════════╡
│ [{1,null}, {null,2}] │ # [{"a": 1, b: None}, {"a": None: b: 2}]
└──────────────────────┘

Polars 将架构确定为:[ {"a": int, "b": int } ]

>>> df.schema
OrderedDict([('a', List(Struct([Field('a', Int32), Field('b', Int32)])))])

这基本上意味着:列中的每个结构都必须具有相同的字段名称。(键)

如果我们取你的起始列表:、、、、都是关键。abcde

list1 = [("a", 1), ("b", 2)]
list2 = [("c", 3), ("d", 4), ("e", 5)]
>>> dict(list1)
{'a': 1, 'b': 2}
>>> dict(list2)
{'c': 3, 'd': 4, 'e': 5}

如果你想要你所展示的结构,你实际上是在说你想要这个:

list1 = [{"key": "a", "value": 1}, {"key": "b", "value": 2}]
list2 = [{"key": "c", "value": 3}, {"key": "d", "value": 4}, {"key": "e", "value": 5}]

即,您的起始必须成为实际

评论

0赞 vinnewbie 11/19/2023
不,“a”、“b”等与 1、2 等一样多。但是,由于我已经解决了这个问题,因此我将不胜感激,以帮助解决直接为此指定架构的新问题。谢谢!!
0赞 jqurious 11/19/2023
@vinnewbie 是的,我知道你想把它们用作“值”,但如果你看一下它们的输出,它们最终会成为结果字典中的“键”。这就是我试图表达的观点。dict(list1)