#python #numpy #unique
#python #numpy #уникальный
Вопрос:
У меня есть таблица данных, в которой есть столбцы string и integer, такие как:
test_data = [('A',1,2,3),('B',4,5,6),('A',1,2,3)]
Мне нужны уникальные строки, поэтому я использовал уникальную функцию numpy:
summary, repeat = np.unique(test_data,return_counts=True, axis=0)
Но после этого мои типы данных меняются. Итог таков:
array([['A', '1', '2', '3'],
['B', '4', '5', '6']], dtype='<U1')
Все типы данных теперь являются строковыми. Как я могу предотвратить это изменение? (Python 3.7, numpy 1.16.4)
Комментарии:
1. Вы не можете хранить несколько разных типов данных в массиве. но поскольку все они могут быть символами, python автоматически примет значение char и преобразует их. Если бы вы сохранили их отдельно, вы получили бы целочисленный массив из целых чисел.
2. @jaSnom не совсем «символ», но да, в значительной степени
3. @juanpa.arrivillaga да, вы правы. работа с Java и python на моей работе иногда заставляет меня их смешивать.
4. @juanpa.arrivillaga. технически у вас может быть recarray или массив объектов с кортежами
5. @MadPhysicist конечно, но технически они все еще хранят однородный тип данных, структурированный dtype или object 🙂
Ответ №1:
Если у вас есть объекты Python и вы хотите сохранить их как объекты python, используйте функции python:
unique_rows = set(test_data)
Или еще лучше:
from collections import Counter
rows_and_counts = Counter(test_data)
Эти решения не копируют данные: они сохраняют ссылки на исходные кортежи такими, какие они есть. Решение numpy копирует данные несколько раз: один раз при преобразовании в numpy, по крайней мере, один раз при сортировке и, возможно, больше при обратном преобразовании.
Эти решения имеют O(N)
алгоритмическую сложность, потому что они оба используют хэш-таблицу. unique
Решение numpy использует сортировку и поэтому имеет O(N log N)
сложность.
Комментарии:
1. Основываясь на вашем ответе, я хочу получить список ключей и значений отдельно, например: подсчитано = Счетчик (test_data) сводка, повтор = список (подсчитано.ключи ()), список(подсчитано.значения()). Есть ли какая-либо возможность, что последовательности списков могут отличаться.
2. @kurag. Нет. Ключи и значения словаря всегда возвращаются в одном и том же порядке. Это часть контракта. Счетчик является подклассом dictionary. Если вы действительно беспокоитесь, сделайте
summary = list(counted); repeat = [counted[k] for k in summary]
Ответ №2:
Вы могли бы явно указать свой dtype в функции np.array, предшествующей np.unique:
test_data = [('A',1,2,3),('B',4,5,6),('A',1,2,3)]
test_data = np.array(test_data, dtype=[('letter', '<U1'),
('x', np.int),
('y', np.int),
('z', np.int)])
summary, repeat = np.unique(test_data,return_counts=True, axis=0)
Затем сводка выглядит следующим образом:
array([('A', 1, 2, 3), ('B', 4, 5, 6)],
dtype=[('letter', '<U1'), ('x', '<i4'), ('y', '<i4'), ('z', '<i4')])
Комментарии:
1. Эти данные поступают из таблицы sql, поэтому мне нужно взять типы данных из таблицы sql и добавить к данным.
2. @kurag почему вы используете
numpy
здесь? В любом случае, я не уверен, что понимаю проблему с этим ответом, почему это имеет значение, если оно получено из таблицы SQL?3. @wprazuch Данные взяты из sql и выполнены некоторые операции над ним, на одном этапе мне нужны уникальные строки с количеством повторений). Я могу использовать ваш ответ, но сначала контролирую исходные типы данных. Если я сделал это, я могу использовать также ответ Aratz с изменениями, но ваш ответ будет короче. Но я ищу ответ на numpy сам по себе, если он есть. И, как я уже сказал Арацу, это должно быть в numpy, numpy after operations должен представлять исходную структуру, а не отредактированную версию.
4. @kurag Если это так, то пока мне ничего не приходит в голову
5. @kurag. Вы понимаете, что
np.unique
на самом деле это не так эффективно? Набор Python или счетчик имеют лучшую производительность масштабирования
Ответ №3:
Я думаю, это связано с тем фактом, что в массиве numpy все элементы должны иметь один и тот же тип, вместо этого вы могли бы попытаться проанализировать ваш результат, когда он выйдет из numpy, например:
result = []
for l in summary.tolist():
new_l = []
for v in l:
try:
new_l.append(int(v))
except ValueError:
new_l.append(v)
result.append(tuple(new_l))
Комментарии:
1. спасибо за ответ, но я думаю, что это должно быть в самом numpy. Эта таблица данных большая, а строковый столбец может быть любым столбцом, поэтому, если нет более короткого способа, я напишу подробную функцию синтаксического анализа.