Numpy: python3: регрессия для уникальных массивов объектов dtype = с различными типами элементов (Trac # 2188)

Созданный на 19 окт. 2012  ·  18Комментарии  ·  Источник: numpy/numpy

_Оригинальный билет http://projects.scipy.org/numpy/ticket/2188 от 23.07.2012 , unknown._

протестировано против текущего мастера (присутствует также в 1.6.2):

Если с серией python2.x все работает нормально, без рвоты:

$> python2.7 -c 'import numpy as np; print repr(repr(np.unique(np.array([1,2, None, "str"]))))' 
'array([None, 1, 2, str], dtype=object)'

NB Я сообщить об ошибке на предст здесь отдельно , если еще не подал

он вообще не работает с python3.x:

$> python3.2 -c 'import numpy as np; print(repr(repr(np.unique(np.array([1,2,None, "str"])))))'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.2/dist-packages/numpy/lib/arraysetops.py", line 194, in unique
    ar.sort()
TypeError: unorderable types: int() > NoneType()

всякий раз, когда ИМХО он должен работать правильно - семантика действия unique () не должна подразумевать возможность сортировки элементов

00 - Bug numpy.core

Самый полезный комментарий

Есть обновления по этому поводу? Я столкнулся с этой ошибкой при попытке использовать scikit-learn LabelEncoder в

Все 18 Комментарий

есть свежие идеи по этому поводу?

Единственные варианты реализации unique :

  • сортировка массива
  • помещать все в хеш-таблицу
  • выполнить грубое сравнение == всех объектов со всеми объектами

Только стратегии сортировки и хеширования имеют разумную скорость, и только стратегии сортировки и все против всех имеют разумные накладные расходы памяти для больших массивов. Итак, я думаю, мы могли бы добавить резервные варианты к unique, где, если сортировка не работает, она пробует одну из других стратегий? Но OTOH нехорошо иметь функцию, которая иногда внезапно занимает значительно больше ЦП или памяти в зависимости от того, какой ввод вы ей дадите.

Я бы получил +1 за патч, который добавляет в np.unique параметр strategy = {"sort", "hash", "bruteforce"}, чтобы пользователи со странными данными могли решить, что имеет смысл в их ситуации. Если хочешь написать такую ​​штуку :-)

сначала я подумал, может ли это быть сортировка + хэш-таблица для несортированных элементов (не проверял, используется ли cmp of elements при сортировке элементов массива объектов dtype), поэтому сортировка __cmp__ могла бы разместить их в порядке очереди -первый в очереди?
но затем понял, что это не дает облегчения в целом для несравнимых типов, например, когда это смесь int и str ... поэтому я подумал, возможно ли для dtype = object вывести первые участвующие dtypes и 'unique '(возможно, через сортировку) внутри каждого dtype, возможно, полагаясь на хэш-таблицы для dtypes без __cmp__ ?

только для тех, кому может потребоваться обходной путь, вот как я делаю это с помощью «хеширования» с помощью встроенных наборов для моего случая:

$> python3.3 -c 'import numpy as np; print(np.array(list(set([1,2,"str", None])), dtype=object))' 
[None 1 2 'str']

Не уверен, что вы только что сказали :-)

Но если подумать, сортировка действительно ненадежна для dtype = object
так или иначе. Я, наверное, написал десятки классов, которые переопределяют eq, но
оставьте значение по умолчанию lt , что означает, что уникальный на основе сортировки будет просто
молча вернуть неверный ответ. Думаю, это довольно неприятная ошибка.

Если объекты хешируются, вы можете просто набрать set (arr), чтобы получить уникальный
элементы, но нет гарантии, что они в целом хешируемы. (Но хотя бы
все, что для хешируемых объектов это должно _работать_, что неверно
для сортировки.) Может быть, это будет лучшая реализация по умолчанию
np.unique для массивов объектов.

Вт, 17 сентября 2013 г., 17:40, Ярослав Гальченко <
[email protected]> написал:

сначала я подумал, может ли это быть сортировка + хеш-таблица для несортированных
элементов (не проверял, используется ли _cmp_ элементов при сортировке элементов
dtype объектный массив), поэтому сортировка cmp может разместить их на
заказ «первым пришел - первым пришел»?
но потом понял, что в целом это не помогает
несопоставимые типы, например, когда это смесь int и str ... поэтому я подумал
если для dtype = object можно было бы вывести первое участвующее
dtypes и 'unique' (возможно, через сортировку) внутри каждого dtype, возможно, полагаясь
по хеш-таблицам для типов без cmp ?

-
Ответьте на это письмо напрямую или просмотрите его на Gi tHubhttps: //github.com/numpy/numpy/issues/641#issuecomment -24603047
.

gy ... ok - жестокое описание на Python:

def bucketed_unique(a):
    buckets = {}
    for x in a:
        t = type(x)
        if not (t in buckets):
            buckets[t] = bucket = []
        else:
            bucket = buckets[t]
        bucket.append(x)
    out = []
    for bucket in buckets.itervalues():
        # here could be actually set of conditions instead of blind try/except
        try:
            out.append(np.unique(bucket))
        except:
            out.append(np.array(list(set(bucket)), dtype=object))
    return np.hstack(out)
print bucketed_unique([1, 2, 'str', None, np.nan, None, np.inf, int])
[1 2 'str' None <type 'int'> nan inf]

конечно - для не объектных ndarrays не следует выполнять "ведение"

Этот алгоритм не использует == в качестве определения уникальности. Объекты
разные типы могут быть ==. (Простой пример: 1, 1.0). Его определение не
соответствуют любой стандартной концепции Python.
17 сентября 2013 года в 18:01 «Ярослав Гальченко» [email protected] написал:

конечно - для не объектных ndarrays не следует выполнять "ведение"

-
Ответьте на это письмо напрямую или просмотрите его на Gi tHubhttps: //github.com/numpy/numpy/issues/641#issuecomment -24604740
.

конечно! не уверен, но, возможно, ретроспективный анализ сегментов имеет смысл ... кстати, проблема с банкоматом проявляется также при сравнении с комплексными числами:

$> python3.3 -c 'import numpy as np; print(np.unique(np.array([1, 1.0, 1+0j], dtype=object)))'  
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/numpy/lib/arraysetops.py", line 194, in unique
    ar.sort()
TypeError: unorderable types: float() > complex()

$> python -c 'import numpy as np; print(np.unique(np.array([1, 1.0, 1+0j], dtype=object)))' 
[1]

хотя во второй мысли - какое тогда «уникальное» значение dtype должно быть среди всех доступных вариантов (int / float / complex)? с необъектным массивом это ясно ... с гетерогенным массивом объектов не так - может быть, даже разные dtypes должны поддерживаться как таковые ...

Вот как я решил взорвать argsort на смешанном int / str в py3: https://github.com/pydata/pandas/pull/6222/files

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

использует реализацию хэш-таблицы pandas, но может быть легко заменена / адаптирована к c-коду, я думаю

Кто-нибудь хочет попробовать это? Не уверен, что делать с типами записей.

Есть обновления по этому поводу? Я столкнулся с этой ошибкой при попытке использовать scikit-learn LabelEncoder в

Этот действительно старый. Это еще актуально?

похоже, по крайней мере, с 1.15.4 в debian:

$> python3 --version
Python 3.6.5

$> PYTHONPATH=.. python3 -c 'import numpy as np; print(np.__version__); print(repr(repr(np.unique(np.array([1,2,None, "str"])))))'                                                                                   
1.15.4
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/numpy/lib/arraysetops.py", line 233, in unique
    ret = _unique1d(ar, return_index, return_inverse, return_counts)
  File "/usr/lib/python3/dist-packages/numpy/lib/arraysetops.py", line 281, in _unique1d
    ar.sort()
TypeError: '<' not supported between instances of 'NoneType' and 'int'

Определенно по-прежнему актуально. Просто наткнулся на это, пытаясь вызвать np.unique(x, return_inverse=True) в массиве объектов.

Что касается вопроса о том, как сделать эту работу, когда сортировка не определена: я бы предпочел медленный алгоритм, а не статус-кво, когда возникает ошибка. (По моему опыту, часто, если вам нужны эффективные алгоритмы, вам не следует использовать массив объектов для начала.)

Я думаю, что это запрос функции, а не ошибка. В документации четко указано:

Возвращает _ отсортированные_ уникальные элементы массива.

В случае такого массива, как [1, None] , в python 3 такого отсортированного массива не существует, поскольку сортировка больше не является четко определенной.

Было бы неплохо иметь возможность _не_ возвращать отсортированный массив, это позволило бы некоторые оптимизации.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги