Есть ли функция numpy group по функции?
Есть ли какая-либо функция в numpy для группировки этого массива ниже в первом столбце?
Я не нашел хорошего ответа в Интернете.
>>> a
array([[ 1, 275],
[ 1, 441],
[ 1, 494],
[ 1, 593],
[ 2, 679],
[ 2, 533],
[ 2, 686],
[ 3, 559],
[ 3, 219],
[ 3, 455],
[ 4, 605],
[ 4, 468],
[ 4, 692],
[ 4, 613]])
Требуемый вывод:
array([[[275, 441, 494, 593]],
[[679, 533, 686]],
[[559, 219, 455]],
[[605, 468, 692, 613]]], dtype=object)
Ответы
Ответ 1
Вдохновленный библиотекой Eelco Hoogendoorn, но без его библиотеки и используя тот факт, что первый столбец вашего массива всегда увеличивается.
>>> np.split(a[:, 1], np.cumsum(np.unique(a[:, 0], return_counts=True)[1])[:-1])
[array([275, 441, 494, 593]),
array([679, 533, 686]),
array([559, 219, 455]),
array([605, 468, 692, 613])]
Я не "тайм-аут", но это, вероятно, более быстрый способ решить вопрос:
- Отсутствует собственный цикл python
- Списки результатов представляют собой массивы numpy, в случае, если вам нужно выполнить другие операции numpy, новое преобразование не потребуется.
- Сложность, такая как O (n)
PS: Я написал аналогичную строку, потому что мне нужно было "группировать" результаты np.nonzero:
>>> indexes, values = np.nonzero(...)
>>> np.split(values, np.cumsum(np.unique(indexes, return_counts=True)[1]))
Ответ 2
Пакет numpy_indexed (выражение об отказе: я его автор) стремится заполнить этот пробел в numpy. Все операции в numy-indexed полностью векторизованы, и никакие алгоритмы O (n ^ 2) не пострадали при создании этой библиотеки.
import numpy_indexed as npi
npi.group_by(a[:, 0]).split(a[:, 1])
Обратите внимание, что обычно более эффективно напрямую вычислять релевантные свойства для таких групп (то есть group_by (keys).mean(values)), а не сначала разбивать на массивы list/jagged.
Ответ 3
Numpy здесь не очень удобен, потому что желаемый результат не является массивом целых чисел (это массив объектов списка).
Я предлагаю либо чистый способ Python...
from collections import defaultdict
%%timeit
d = defaultdict(list)
for key, val in a:
d[key].append(val)
10.7 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# result:
defaultdict(list,
{1: [275, 441, 494, 593],
2: [679, 533, 686],
3: [559, 219, 455],
4: [605, 468, 692, 613]})
... или путь панд:
import pandas as pd
%%timeit
df = pd.DataFrame(a, columns=["key", "val"])
df.groupby("key").val.apply(pd.Series.tolist)
979 µs ± 3.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# result:
key
1 [275, 441, 494, 593]
2 [679, 533, 686]
3 [559, 219, 455]
4 [605, 468, 692, 613]
Name: val, dtype: object
Ответ 4
n = np.unique(a[:,0])
np.array( [ list(a[a[:,0]==i,1]) for i in n] )
выходы:
array([[275, 441, 494, 593], [679, 533, 686], [559, 219, 455],
[605, 468, 692, 613]], dtype=object)
Ответ 5
Чтобы упростить ответ Винсента Дж, можно использовать return_index = True
вместо return_counts = True
и избавиться от cumsum
:
np.split(a[:,1], np.unique(idx,return_index = True)[1][1:])
Выход
[array([275, 441, 494, 593]),
array([679, 533, 686]),
array([559, 219, 455]),
array([605, 468, 692, 613])]
Ответ 6
Я использовал np.unique(), а затем np.extract()
unique = np.unique(a[:, 0:1])
answer = []
for element in unique:
present = a[:,0]==element
answer.append(np.extract(present,a[:,-1]))
print (answer)
[array([275, 441, 494, 593]), array([679, 533, 686]), array([559, 219, 455]), array([605, 468, 692, 613])]
Ответ 7
учитывая X как массив элементов, которые вы хотите сгруппировать, а y (массив 1D) как соответствующие группы, следующая функция группирует с помощью numpy:
def groupby(X, y):
y = np.asarray(y)
X = np.asarray(X)
y_uniques = np.unique(y)
return [X[y==yi] for yi in y_uniques]
Итак, groupby(a[:,1], a[:,0])
возвращается
[array([275, 441, 494, 593]), array([679, 533, 686]), array([559, 219, 455]), array([605, 468, 692, 613])]