Создание столбца с набором повторяет набор n раз - PullRequest
4 голосов
/ 09 марта 2020

Я столкнулся с этим неожиданным поведением, используя pandas, который я не совсем понимаю, как объяснить, и не нашел здесь связанных вопросов в SO.

При создании кадра данных из словаря списков, как и ожидалось, мы получаем каждый элемент из итерируемого в новую строку в столбцах, указанных данным key:

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

   a
0  1
1  2
2  3

Однако , пытаясь сделать то же самое с 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'

1 Ответ

3 голосов
/ 09 марта 2020

Проблема в 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

Построение по указанию продлится go через этот блок

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])


Поскольку при извлечении индекса возникает проблема, простой обходной прием - указать индекс, чтобы он не go ни через один из них.

pd.DataFrame({'a': {1,2,3}}, index=[0])
#           a
#0  {1, 2, 3}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...