Предполагая, что у меня есть массив numpy: [1,2,3,4,5,6] и еще один массив: [0,0,1,2,2,1] Я хочу суммировать элементы в первом массиве по группе (второй массив) и получить результаты n-групп в порядке порядкового номера группы (в этом случае результат будет [3, 9, 9]). Как это сделать в numpy?Сумма массива по номеру в numpy
ответ
Там больше, чем один из способов сделать это, но вот один из способов:
import numpy as np
data = np.arange(1, 7)
groups = np.array([0,0,1,2,2,1])
unique_groups = np.unique(groups)
sums = []
for group in unique_groups:
sums.append(data[groups == group].sum())
Вы можете Vectorize вещи так, что там нет для петли на всех, но я рекомендовал бы против него. Он становится нечитаемым и потребует пару временных временных массивов 2D, которые могут потребовать больших объемов памяти, если у вас много данных.
Редактировать: Вот один из способов, которым вы можете полностью векторизовать. Имейте в виду, что это может (и, скорее всего, будет) медленнее, чем версия выше. (И может быть лучший способ его векторизации, но уже поздно, и я устал, так что это первое, что появляется в моей голове ...)
Однако имейте в виду, что это плохой пример ... Вы действительно лучше (как с точки зрения скорости и читаемости) с указанным выше петли ...
import numpy as np
data = np.arange(1, 7)
groups = np.array([0,0,1,2,2,1])
unique_groups = np.unique(groups)
# Forgive the bad naming here...
# I can't think of more descriptive variable names at the moment...
x, y = np.meshgrid(groups, unique_groups)
data_stack = np.tile(data, (unique_groups.size, 1))
data_in_group = np.zeros_like(data_stack)
data_in_group[x==y] = data_stack[x==y]
sums = data_in_group.sum(axis=1)
Спасибо! Память не проблема, и я бы хотел избежать циклов. Как бы вы это обозначили? – 2010-12-07 05:57:15
@Scribble Master - см. Редактирование ... Однако нет ничего плохого в том, чтобы перебирать уникальные группы. Вторая версия, вероятно, будет медленной, и чертовски трудно читать. С циклом вы только зацикливаете (в python, во всяком случае) на количество уникальных групп. Внутреннее сравнение `data [groups == group]` будет довольно быстрым. – 2010-12-07 06:14:38
чистая реализация питон:
l = [1,2,3,4,5,6]
g = [0,0,1,2,2,1]
from itertools import izip
from operator import itemgetter
from collections import defaultdict
def group_sum(l, g):
groups = defaultdict(int)
for li, gi in izip(l, g):
groups[gi] += li
return map(itemgetter(1), sorted(groups.iteritems()))
print group_sum(l, g)
[3, 9, 9]
Если группы индексированные целыми целыми числами, вы можете злоупотреблять функцией numpy.histogram()
, чтобы получить результат:
data = numpy.arange(1, 7)
groups = numpy.array([0,0,1,2,2,1])
sums = numpy.histogram(groups,
bins=numpy.arange(groups.min(), groups.max()+2),
weights=data)[0]
# array([3, 9, 9])
Это позволит избежать любых петель Python.
Это векторный метод выполнения этой суммы, основанный на реализации numpy.unique. По моим таймингам это до 500 раз быстрее, чем метод петли и в 100 раз быстрее, чем метод гистограммы.
def sum_by_group(values, groups):
order = np.argsort(groups)
groups = groups[order]
values = values[order]
values.cumsum(out=values)
index = np.ones(len(groups), 'bool')
index[:-1] = groups[1:] != groups[:-1]
values = values[index]
groups = groups[index]
values[1:] = values[1:] - values[:-1]
return values, groups
NumPy функция bincount
была сделана именно для этой цели, и я уверен, что это будет гораздо быстрее, чем другие методы для всех размеров входов:
data = [1,2,3,4,5,6]
ids = [0,0,1,2,2,1]
np.bincount(ids, weights=data) #returns [3,9,9] as a float64 array
Я-й элемент выход представляет собой сумму всех элементов data
, соответствующих «id» i
.
Надеюсь, что это поможет.
Я попробовал сценарии из всех, и мои соображения:
Джо: Будет работать только если у вас есть несколько групп.
kevpie: Слишком медленно из-за петель (это не вещий способ)
Bi_Rico и Sven: выполнять хорошо, но будет работать только для Int32 (если сумма берется по 2^32/2 она не будет выполнена)
Alex: самый быстрый, полезный для суммы.
Но если вы хотите больше гибкости и возможности группировать по другой статистике использование SciPy:
from scipy import ndimage
data = np.arange(10000000)
groups = np.arange(1000).repeat(10000)
ndimage.sum(data, groups, range(1000))
Это хорошо, потому что у вас есть много статистических данных для группы (суммы, среднего значения, дисперсии, ...).
я заметил numpy
тег, но в случае, если вы не возражаете против использования pandas
, эта задача становится один вкладыш:
import pandas as pd
import numpy as np
data = np.arange(1, 7)
groups = np.array([0, 0, 1, 2, 2, 1])
df = pd.DataFrame({'data': data, 'groups': groups})
Так df
будет выглядеть следующим образом:
data groups
0 1 0
1 2 0
2 3 1
3 4 2
4 5 2
5 6 1
сейчас вы можете использовать функции groupby()
и sum()
print df.groupby(['groups'], sort=False).sum()
, который дает желаемый результат
data
groups
0 3
1 9
2 9
По умолчанию dataframe будет отсортирован, поэтому я использую флаг sort=False
, которые могли бы улучшить скорость для огромных dataframes.
Вы все ошибаетесь! Наилучший способ сделать это:
a = [1,2,3,4,5,6]
ix = [0,0,1,2,2,1]
accum = np.zeros(np.max(ix)+1)
np.add.at(accum, ix, a)
print accum
> array([ 3., 9., 9.])
- 1. NumPy сумма массива уменьшить
- 2. Сумма массивы значений по номеру недели
- 3. Сумма Numpy массива на основе другого массива
- 4. Сумма продаж по типовому номеру статьи SQL
- 5. сумма неровных сегментов массива в numpy
- 6. Сортировка многомерного массива по номеру
- 7. Looping oci_fetch_all массива по номеру
- 8. Сортировка массива словарей по номеру
- 9. PHP: сортировка массива по номеру
- 10. Сумма SymPy выражение над NumPy массива
- 11. Справка по сортировке по номеру
- 12. сумма NumPy массива при заданных показателей
- 13. Сумма массива по-другому
- 14. Сумма Python по сравнению с numpy.sum NumPy
- 15. Систематически перемещаясь по каждому номеру в массив numpy
- 16. NumPy сумма не согласен
- 17. Сумма значений NumPy массива на основе меток в отдельном массиве
- 18. Сумма гауссианцев в быстром Numpy?
- 19. Сумма массива ячеек по столбцу
- 20. Векторизованная сумма массива по показателям второго массива
- 21. NumPy: Limited накопленная сумма
- 22. Python NumPy сумма (-1)
- 23. Расщепление NumPy массива по BOOL
- 24. NumPy: точка сумма
- 25. Сортировка массива numpy по сумме
- 26. Сумма отрицательных элементов в каждом столбце массива NumPy
- 27. Вычесть Numpy массива по столбцам
- 28. Поведение индексирования по номеру
- 29. Сумма фрагментов последовательных значений в массиве NumPy
- 30. Ограниченная сумма или разность массивов в numpy
Зачем вам нужно numpy для этого? Разве вы не используете списки ванильных питонов? Если нет, какой тип numpy вы используете? – 2010-12-07 05:19:40
Мне нужно numpy для этого, потому что я не хочу прокручивать массив n-times для n групп, так как размеры массива могут быть сколь угодно большими. Я не использую списки python, я просто показывал пример данных в скобках. Тип данных - int. – 2010-12-07 05:31:37
http://www.stackoverflow.com/questions/7089379/most-efficient-way-to-sum-huge-2d-numpy-array-grouped-by-id-column – TooTone 2014-04-11 10:42:59