2015-03-27 4 views
7

Скажут, у меня есть произвольный Numpy матрица, которая выглядит следующим образом:Group и средняя Numpy Матрица

arr = [[ 6.0 12.0 1.0] 
[ 7.0 9.0 1.0] 
[ 8.0 7.0 1.0] 
[ 4.0 3.0 2.0] 
[ 6.0 1.0 2.0] 
[ 2.0 5.0 2.0] 
[ 9.0 4.0 3.0] 
[ 2.0 1.0 4.0] 
[ 8.0 4.0 4.0] 
[ 3.0 5.0 4.0]] 

Что бы эффективный способ усреднения строк, которые сгруппированы по третьему номеру столбца?

Ожидаемый результат будет:

result = [[ 7.0 9.33 1.0] 
[ 4.0 3.0 2.0] 
[ 9.0 4.0 3.0] 
[ 4.33 3.33 4.0]] 
+0

гарантированные ли строки, чтобы быть в порядке третьей колонкой? – Sniggerfardimungus

+2

Можете ли вы использовать Панды? – dawg

+0

@Sniggerfardimungus Да, можно предположить, что третий столбец будет отсортирован. – Algorithm

ответ

3

Вы можете сделать:

for x in sorted(np.unique(arr[...,2])): 
    results.append([np.average(arr[np.where(arr[...,2]==x)][...,0]), 
        np.average(arr[np.where(arr[...,2]==x)][...,1]), 
        x]) 

Тестирование:

>>> arr 
array([[ 6., 12., 1.], 
     [ 7., 9., 1.], 
     [ 8., 7., 1.], 
     [ 4., 3., 2.], 
     [ 6., 1., 2.], 
     [ 2., 5., 2.], 
     [ 9., 4., 3.], 
     [ 2., 1., 4.], 
     [ 8., 4., 4.], 
     [ 3., 5., 4.]]) 
>>> results=[] 
>>> for x in sorted(np.unique(arr[...,2])): 
...  results.append([np.average(arr[np.where(arr[...,2]==x)][...,0]), 
...      np.average(arr[np.where(arr[...,2]==x)][...,1]), 
...      x]) 
... 
>>> results 
[[7.0, 9.3333333333333339, 1.0], [4.0, 3.0, 2.0], [9.0, 4.0, 3.0], [4.333333333333333, 3.3333333333333335, 4.0]] 

Массив arr не должен быть отсортирован, и все промежуточные массивы представлений (т.е. не новые массивы данных). Среднее значение рассчитывается эффективно непосредственно из этих представлений.

+0

Мне это нравится, очень чисто. Как я могу вместо этого сохранить результат в numpy.array? – Algorithm

+0

Я обнаружил, что самый простой способ - просто преобразовать результаты впоследствии в любой заданный тип. Таким образом, у меня есть 'results = np.asarray (results)', и выход прекрасен. – Algorithm

+0

Могу ли я спросить, почему голос? – dawg

3

решение

from itertools import groupby 
from operator import itemgetter 

arr = [[6.0, 12.0, 1.0], 
     [7.0, 9.0, 1.0], 
     [8.0, 7.0, 1.0], 
     [4.0, 3.0, 2.0], 
     [6.0, 1.0, 2.0], 
     [2.0, 5.0, 2.0], 
     [9.0, 4.0, 3.0], 
     [2.0, 1.0, 4.0], 
     [8.0, 4.0, 4.0], 
     [3.0, 5.0, 4.0]] 

result = [] 

for groupByID, rows in groupby(arr, key=itemgetter(2)): 
    position1, position2, counter = 0, 0, 0 
    for row in rows: 
     position1+=row[0] 
     position2+=row[1] 
     counter+=1 
    result.append([position1/counter, position2/counter, groupByID]) 

print(result) 

бы выход:

[[7.0, 9.333333333333334, 1.0]] 
[[4.0, 3.0, 2.0]] 
[[9.0, 4.0, 3.0]] 
[[4.333333333333333, 3.3333333333333335, 4.0]] 
+0

удаленных списков, чтобы сделать его память- friendly – DmitrySemenov

+0

Я думаю, что это лучшее решение ... –

2
arr = np.array(
[[ 6.0, 12.0, 1.0], 
[ 7.0, 9.0, 1.0], 
[ 8.0, 7.0, 1.0], 
[ 4.0, 3.0, 2.0], 
[ 6.0, 1.0, 2.0], 
[ 2.0, 5.0, 2.0], 
[ 9.0, 4.0, 3.0], 
[ 2.0, 1.0, 4.0], 
[ 8.0, 4.0, 4.0], 
[ 3.0, 5.0, 4.0]]) 
np.array([a.mean(0) for a in np.split(arr, np.argwhere(np.diff(arr[:, 2])) + 1)]) 
4

Компактное решение заключается в использовании numpy_indexed (отказа от ответственности: Я его автор), который реализует полностью векторизованное решение:

import numpy_indexed as npi 
npi.group_by(arr[:, 2]).mean(arr) 
Смежные вопросы