Как рассчитать скользящее среднее для массива NumPy с различными размерами окон, определяемыми массивом индексов? - PullRequest
0 голосов
/ 11 октября 2018

Какой самый питонический способ усреднить значения в 2d массиве (ось = 1) на основе диапазона в 1d массиве?

Я пытаюсь усреднить массивы переменных среды (мой 2d массив) на основе каждых 2 градусов широты (мой массив идентификаторов).У меня есть массив широты, который идет от -33,9 до 29,5.Я бы хотел усреднить переменные среды в пределах каждых 2 градусов от -34 до 30.

Количество элементов в каждых 2 градусах может быть различным, например:

arr = array([[5,3,4,5,6,4,2,4,5,8],
             [4,5,8,5,2,3,6,4,1,7],
             [8,3,5,8,5,2,5,9,9,4]])

idx = array([1,1,1,2,2,3,3,3,3,4])

Iбудет затем усреднить значения в arr на основе idx[0:3], idx[3:9], idx[9].

Я хотел бы получить результат:

arrAvg = array([4,4.2,8],
               [6.3,3.5,7],
               [5.3,6.3,4]) 

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

@ Andyk уже объяснил в своем посте, как рассчитать среднее значение, имея список индексов.
Я предоставлю решение для получения этих индексов.

Вот общееподход:

from typing import Optional

import numpy as np


def get_split_indices(array: np.ndarray,
                      *,
                      window_size: int,
                      start_value: Optional[int] = None) -> np.ndarray:
    """
    :param array: input array with consequent integer indices
    :param window_size: specifies range of indices
    which will be included in a separate window
    :param start_value: from which the window will start
    :return: array of indices marking the borders of the windows
    """
    if start_value is None:
        start_value = array[0]

    diff = np.diff(array)
    diff_indices = np.where(diff)[0] + 1

    slice_ = slice(window_size - 1 - (array[0] - start_value) % window_size,
                   None,
                   window_size)

    return diff_indices[slice_]

Примеры использования:

Сверяя это с данными вашего примера:

# indices:             3            9
idx = np.array([1,1,1, 2,2,3,3,3,3, 4])

вы можете получитьиндексы, разделяющие разные окна, например:

get_split_indices(idx,
                  window_size=2,
                  start_value=0)
>>> array([3, 9])

С помощью этой функции вы также можете указать разные размеры окна:

# indices:                     7        11               17
idx = np.array([0,1,1,2,2,3,3, 4,5,6,7, 8,9,10,11,11,11, 12,13])

get_split_indices(idx,
                  window_size=4,
                  start_value=0)
>>> array([ 7, 11, 17])

и разные начальные значения:

# indices:         1            7      10     13              18
idx = np.array([0, 1,1,2,2,3,3, 4,5,6, 7,8,9, 10,11,11,11,12, 13])
get_split_indices(idx,
                  window_size=3,
                  start_value=-2)
>>> array([ 1,  7, 10, 13, 18])

Обратите внимание, что по умолчанию я сделал первый элемент массива начальным.

0 голосов
/ 11 октября 2018

Вы можете использовать функцию np.hsplit.Для вашего примера индексов 0:3, 3:9, 9 это выглядит так:

np.hsplit(arr, [3, 9])

, который дает вам список массивов:

[array([[5, 3, 4],
        [4, 5, 8],
        [8, 3, 5]]), 
 array([[5, 6, 4, 2, 4, 5],
        [5, 2, 3, 6, 4, 1],
        [8, 5, 2, 5, 9, 9]]), 
 array([[8],
        [7],
        [4]])]

Затем вы можете вычислить среднее значение следующим образом:

m = [np.mean(a, axis=1) for a in np.hsplit(arr, [3, 9])]

И преобразовать его обратно в массив:

np.vstack(m).T
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...