Средний расчет в Python - PullRequest
       6

Средний расчет в Python

0 голосов
/ 23 декабря 2018

Я пытаюсь ускорить фрагмент кода Python.

Учитывая два одинаковых (numpy) массива, цель состоит в том, чтобы найти среднее значение в одном массиве, скажем, a, соответствующее значениямдругой массив, скажем, б.Индексы массивов синхронизированы.

Например;

a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])

Есть два различных значения в a, 1 и 2. Значения в b, где есть «1» в a втем же индексом являются [10, 10, 10].Следовательно, среднее значение (1) равно 10. Аналогично, среднее значение (2) равно 20.

Можно предположить, что различные наборы значений в a являются известными априори.Значения в a не обязательно должны быть последовательными, порядок случайный.Я выбрал пример как таковой, чтобы облегчить описание.

Вот как я подошел:

   # Accumulate the total sum and count
    for index, val in np.ndenumerate(a):
        val_to_sum[val] += b[index]
        val_to_count[val] += 1

    # Calculate the mean
    for val in val_to_sum.keys():
        if val_to_count[val]:  # skip vals with zero count
            val_to_mean[val] = val_to_sum[val] / val_to_count[val]

Здесь val_to_sum и val_to_count - это словари, которые инициализируются нулями на основе известного списка значений, которые можно увидеть в a (в данном случае 1 и 2).

Я сомневаюсь, что это самый быстрый способ его расчета.Я ожидаю, что списки будут довольно длинными, скажем, несколько миллионов, а набор возможных значений будет порядка десятков.

Как я могу ускорить это вычисление?

Может ли быть решение? Вдохновленный одним из ответов ниже, это может сделать это:

for val in a 
  b[a==val].mean() 

Ответы [ 3 ]

0 голосов
/ 23 декабря 2018

Это можно сделать, удалив дубликат: Итак, попробуйте это:

from collections import OrderedDict
import numpy as np
a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])

a=list(OrderedDict.fromkeys(a))
b=list(OrderedDict.fromkeys(b))  
print(b)  

, если у вас есть разные элементы в b, поэтому используйте этот код

import pandas as pd
import numpy as np
a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])   
d = {}

for l, n in zip(a, b):
    d.setdefault(l, []).append(n)

for key in d:
    print key, sum(d[key])/len(d[key])

: https://onlinegdb.com/BJih3DplE

0 голосов
/ 23 декабря 2018

Вы можете просмотреть список один раз:

means_dict = {}
for i in range(len(a)):
    val = a[i]
    n = b[i]
    if val not in means_dict.keys():
        means_dict[val] = np.array([0.0,0.0])
    arr = means_dict[val]
    arr[0] = arr[0] * (arr[1] / (arr[1] + 1)) + n * (1 / (arr[1] + 1))
    arr[1] = arr[1] + 1

вычисление скользящего среднего для каждого из значений.в конце у вас будет дикт, с каждым значением avarage и количеством.

Edit:
На самом деле, тренировка показала, что это дает наилучшие результаты:

def f3(a,b):
    means = {}
    for val in set(a):
      means[val] = np.average(b[a==val]) 
    return means

Что похоже на то, что вы предложили, просто перейти на set, сэкономив много времени.

0 голосов
/ 23 декабря 2018

Возможно, что-то подобное будет работать:

import numpy as np

a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])

np.average(b[a==1])
np.average(b[a==2])

Для больших наборов данных:

import numpy as np

a = np.random.randint(1,30,1000000)
b = np.random.random(size=1000000)

for x in set(a):
  print("Average for values marked {0}: {1}".format(x,np.average(b[a==x])))
...