我试图从字典(mainDict)中创建一个极地数据帧,其中mainDict的值之一是字典对象列表(nestedDicts)。当我尝试这样做时,我得到了一个我不知道含义的错误(见下文)。但是,pandas允许我使用mainDict创建一个数据框架。
我不确定是否我做错了什么,如果它是一个错误,或者如果这个操作只是不支持的极地。我不太担心找到一个变通方法,因为它应该是直截了当的(欢迎提出建议),但如果可能的话,我想这样做。
我在谷歌colab上的极地版本0.13.38(问题也发生在VScode本地,python版本3.9.6和windows 10)。下面是再现问题及其输出的代码示例。谢谢!
输入:
import polars as pl
import pandas as pd
template = { 'a':['A', 'AA'],
'b':['B', 'BB'],
'c':['C', 'CC'],
'd':[{'D1':'D2'}, {'DD1':'DD2'}]}
#create a dataframe using pandas
df_pandas = pd.DataFrame(template)
print(df_pandas)
#create a dataframe using polars
df_polars = pl.DataFrame(template)
print(df_polars)
输出:
a b c d
0 A B C {'D1': 'D2'}
1 AA BB CC {'DD1': 'DD2'}
---------------------------------------------------------------------------
ComputeError Traceback (most recent call last)
<ipython-input-9-2abdc86d91da> in <module>()
12
13 #create a dataframe using polars
---> 14 df_polars = pl.DataFrame(template)
15 print(df_polars)
3 frames
/usr/local/lib/python3.7/dist-packages/polars/internals/frame.py in __init__(self, data, columns, orient)
300
301 elif isinstance(data, dict):
--> 302 self._df = dict_to_pydf(data, columns=columns)
303
304 elif isinstance(data, np.ndarray):
/usr/local/lib/python3.7/dist-packages/polars/internals/construction.py in dict_to_pydf(data, columns)
400 return PyDataFrame(data_series)
401 # fast path
--> 402 return PyDataFrame.read_dict(data)
403
404
/usr/local/lib/python3.7/dist-packages/polars/internals/series.py in __init__(self, name, values, dtype, strict, nan_to_null)
225 self._s = self.cast(dtype, strict=True)._s
226 elif isinstance(values, Sequence):
--> 227 self._s = sequence_to_pyseries(name, values, dtype=dtype, strict=strict)
228 elif _PANDAS_AVAILABLE and isinstance(values, (pd.Series, pd.DatetimeIndex)):
229 self._s = pandas_to_pyseries(name, values)
/usr/local/lib/python3.7/dist-packages/polars/internals/construction.py in sequence_to_pyseries(name, values, dtype, strict)
241 if constructor == PySeries.new_object:
242 try:
--> 243 return PySeries.new_from_anyvalues(name, values)
244 # raised if we cannot convert to Wrap<AnyValue>
245 except RuntimeError:
ComputeError: struct orders must remain the same
您收到的错误是因为您的字典列表不符合polar中Series
或struct
的期望。更具体地说,您的两个字典{'D1':'D2'}
和{'DD1':'DD2'}
在polar中被映射到两种不同类型的结构体,因此对于包含在同一个Series
中是不兼容的。
我首先需要解释结构…
高偏振星:结构体
在polar中,字典被映射到称为struct
的东西。结构体是一个有序的命名,类型化数据的集合。(在这方面,结构体很像只有一行的PolarsDataFrame
。)
在struct中:
- 每个字段必须有一个唯一的字段名 每个字段都有一个数据类型
- 为
极性:将字典映射到结构
当字典映射到结构体时(例如,在DataFrame
构造函数中),字典中的每个键都映射到结构体中的字段名,并将相应的字典值赋给结构体中该字段的值。
同样,键在字典中的顺序也很重要:struct
字段的创建顺序与字典中的键的顺序相同。在Python中,很容易忘记字典中的键是有序的。
在3.7版更改:字典顺序保证为插入顺序。此行为是CPython从3.6开始的实现细节。
极性:结构体的系列/列表
这就是你的输入在polar中遇到麻烦的地方。只有满足以下条件,一个结构的集合才能包含在同一个Series
中:
- 结构体具有相同数量的字段
- 字段名称相同
- 字段顺序相同
- 每个结构体的每个字段的数据类型是相同的。
在您的输入中,{'D1':'D2'}
被映射到一个结构体,其中一个字段的字段名为"D1"值为"d2"。但是,{'DD1':'DD2'}
被映射到一个结构体,其中有一个字段名为";dd1 &;"和value "DD2"。因此,结果结构不兼容,不能包含在同一个Series
中。它们的字段名不匹配。
在本例中,北极星是far比Pandas更挑剔,后者允许具有任意键值对的字典出现在同一列中。
总的来说,你会发现polar在数据结构和数据类型方面比Pandas更加固执己见。(部分原因与性能有关。)工作区
您的示例的一个解决方法是更改字典,使它们以相同的顺序包含相同的键。例如:
template = {
"a": ["A", "AA"],
"b": ["B", "BB"],
"c": ["C", "CC"],
"d": [{"D1": "D2", "DD1": None}, {"D1": None, "DD1": "DD2"}],
}
pl.DataFrame(template)
shape: (2, 4)
┌─────┬─────┬─────┬──────────────┐
│ a ┆ b ┆ c ┆ d │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ struct[2] │
╞═════╪═════╪═════╪══════════════╡
│ A ┆ B ┆ C ┆ {"D2",null} │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ AA ┆ BB ┆ CC ┆ {null,"DD2"} │
└─────┴─────┴─────┴──────────────┘
另一个简单的解决方法是首先将数据导入Pandas,然后将Pandas DataFrame导入polar。导入过程将为您完成这项工作。
template = {
"a": ["A", "AA"],
"b": ["B", "BB"],
"c": ["C", "CC"],
"d": [{"D1": "D2"}, {"DD1": "DD2"}],
}
pl.DataFrame(pd.DataFrame(template))
>>> pl.DataFrame(pd.DataFrame(template))
shape: (2, 4)
┌─────┬─────┬─────┬──────────────┐
│ a ┆ b ┆ c ┆ d │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ struct[2] │
╞═════╪═════╪═════╪══════════════╡
│ A ┆ B ┆ C ┆ {"D2",null} │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ AA ┆ BB ┆ CC ┆ {null,"DD2"} │
└─────┴─────┴─────┴──────────────┘
可能有其他解决方法,但这取决于您的具体数据和需求。