首页 > 解决方案 > 使用集合创建列会复制集合 n 次

问题描述

我在使用 pandas 时遇到了这种我不太知道如何解释的意外行为,并且在 SO 中没有找到任何相关问题。

从列表字典创建数据框时,正如预期的那样,我们将迭代中的每个元素放入给定的列中的新行中key

pd.DataFrame({'a':[1,2,3]})

   a
0  1
1  2
2  3

但是,尝试对 a 执行相同操作会set产生:

pd.DataFrame({'a':{1,2,3}})

       a
0  {1, 2, 3}
1  {1, 2, 3}
2  {1, 2, 3}

所以似乎该集合被复制到它实际包含的元素数量,即 3。

我知道为此使用集合并没有什么意义,因为集合根据定义是无序的集合。但是我找不到这种行为背后的任何参考或解释。这是在文档中的某处指定的吗?这背后有什么明显的原因让我想念吗?

pd.__version__
# '1.0.0'

标签: pythonpandasset

解决方案


问题出在extract_index,也有点sanitize_array。给出完整的演练:

import pandas as pd
from pandas.core.internals.construction import init_dict

#pd.DataFrame({'a':{1,2,3}})
data = {'a': {1,2,3}}
index = None
columns = None
dtype = None

从 dict 构造将通过这个块

elif isinstance(data, dict):
    mgr = init_dict(data, index, columns, dtype=dtype)

您可以看到索引不正确:

BlockManager
Items: Index(['a'], dtype='object')
Axis 1: RangeIndex(start=0, stop=4, step=1)
ObjectBlock: slice(0, 1, 1), 1 x 4, dtype: object

发生这种情况是因为init_dict这样做,它传递arrays=[{1, 2, 3}]extract_index并且 pandas 认为一个集合是list_like。这意味着它将这个集合的长度作为您的索引长度

from pandas.core.dtypes.common import is_list_like

is_list_like({1,2,3})
#True

另一个问题是由于ndim存储列表或集合的数组不同,因此底层np.array的创建方式不同。这被埋在这里

np.array({1,2,3}).ndim
#0

np.array([1,2,3]).ndim
#1

因此,该集合被视为“标量”,它被广播到上面指定的整个 RangeIndex 成为array([{1, 2, 3}, {1, 2, 3}, {1, 2, 3}], dtype=object),而列表保持为array([1, 2, 3])


因为它在提取索引时遇到问题,所以简单的解决方法是指定索引,这样它就不会经历任何这些。

pd.DataFrame({'a': {1,2,3}}, index=[0])
#           a
#0  {1, 2, 3}

推荐阅读