Как получить все возможные кусочки одномерного массива в зависимости от ввода - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть массив NumPy

a = np.arange(12)
>>> [0,1,2,3,4,5,6,7,8,9,10,11]

Я пытаюсь вычислить все возможные суммы, как это

np.cumsum[2:] + np.cumsum[:-2]
np.cumsum[3:] + np.cumsum[:-3]
...
np.cumsum[11:] + np.cumsum[:-11]

Как мне этого добиться без петли? Я пытался сделать

starts = np.arange(2,12)
np.cumsum[starts:] + np.cumsum[:-starts]
but I get this error
TypeError: only integer scalar arrays can be converted to a scalar index

Как мне это сделать без цикла for

Что я пытаюсь сделать

Я пытаюсь вычислить скользящее среднее всех возможных периодов времени в пределах длины последовательности. Например, если бы у меня был размер массива 10, я мог бы сделать скользящее среднее 1 период (не имеет смысла), скользящее среднее 2 периода, 3 периода ... 10 периодов. Как мне это сделать. Я хочу вычислить скользящее среднее от 2 до n, где n - размер последовательности

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Это не то, что вы просили.Но если вы ищете более простое решение, вы можете использовать подход панды.

df = pd.DataFrame({'a' :np.arange(11)})  # your data 
window_lengths = np.arange(2,len(a))  # define window lengths from 2 to n
[rolling_win.mean() for rolling_win in [df.rolling(length) for length in window_lengths]]

вывод:

 [      a
     0   NaN
     1   0.5
     2   1.5
     3   2.5
     4   3.5
     5   4.5
     6   5.5
     7   6.5
     8   7.5
     9   8.5
     10  9.5,       a
     0   NaN
     1   NaN
     2   1.0
     3   2.0
     4   3.0
     5   4.0
     6   5.0
     7   6.0
     8   7.0
     9   8.0
     10  9.0,       a
     0   NaN
     1   NaN
     2   NaN
     3   1.5
     4   2.5
     5   3.5
     6   4.5
     7   5.5
     8   6.5
     9   7.5
     10  8.5,       a
     0   NaN
     1   NaN
     2   NaN
     3   NaN
     4   2.0
     5   3.0
     6   4.0
     7   5.0
     8   6.0
     9   7.0
     10  8.0,       a
     0   NaN
     1   NaN
     2   NaN
     3   NaN
     4   NaN
     5   2.5
     6   3.5
     7   4.5
     8   5.5
     9   6.5
     10  7.5,       a
     0   NaN
     1   NaN
     2   NaN
     3   NaN
     4   NaN
     5   NaN
     6   3.0
     7   4.0
     8   5.0
     9   6.0
     10  7.0,       a
     0   NaN
     1   NaN
     2   NaN
     3   NaN
     4   NaN
     5   NaN
     6   NaN
     7   3.5
     8   4.5
     9   5.5
     10  6.5,       a
     0   NaN
     1   NaN
     2   NaN
     3   NaN
     4   NaN
     5   NaN
     6   NaN
     7   NaN
     8   4.0
     9   5.0
     10  6.0,       a
     0   NaN
     1   NaN
     2   NaN
     3   NaN
     4   NaN
     5   NaN
     6   NaN
     7   NaN
     8   NaN
     9   4.5
     10  5.5]
0 голосов
/ 26 апреля 2018

Не уверен, что я полностью понял вопрос, вот что вы можете использовать в качестве отправной точки.

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

In [3]: a = np.arange(12)

In [4]: a
Out[4]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

In [15]: starts = np.arange(2,12)

In [18]: left = np.stack([np.pad(a,(0,s),mode="constant")[s:] for s in starts])

In [19]: left
Out[19]: 
array([[ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  0],
       [ 3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  0,  0],
       [ 4,  5,  6,  7,  8,  9, 10, 11,  0,  0,  0,  0],
       [ 5,  6,  7,  8,  9, 10, 11,  0,  0,  0,  0,  0],
       [ 6,  7,  8,  9, 10, 11,  0,  0,  0,  0,  0,  0],
       [ 7,  8,  9, 10, 11,  0,  0,  0,  0,  0,  0,  0],
       [ 8,  9, 10, 11,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 9, 10, 11,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [10, 11,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [11,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0]])

Здесь вам также нужно сместить все влево, чтобы получить правильное выравнивание:

In [27]: right = np.stack([ np.roll(np.pad(a, (s,0), mode="constant")[:-s], -s) for s in starts ])

In [28]: right
Out[28]: 
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0],
       [0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0],
       [0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0],
       [0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0],
       [0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0],
       [0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

ТеперьВы можете использовать векторизованный np.cumsum для интенсивной части

In [41]: np.cumsum(left, axis=1) + np.cumsum(right, axis=1)
Out[41]:
array([[  2,   6,  12,  20,  30,  42,  56,  72,  90, 110, 110, 110],
       [  3,   8,  15,  24,  35,  48,  63,  80,  99,  99,  99,  99],
       [  4,  10,  18,  28,  40,  54,  70,  88,  88,  88,  88,  88],
       [  5,  12,  21,  32,  45,  60,  77,  77,  77,  77,  77,  77],
       [  6,  14,  24,  36,  50,  66,  66,  66,  66,  66,  66,  66],
       [  7,  16,  27,  40,  55,  55,  55,  55,  55,  55,  55,  55],
       [  8,  18,  30,  44,  44,  44,  44,  44,  44,  44,  44,  44],
       [  9,  20,  33,  33,  33,  33,  33,  33,  33,  33,  33,  33],
       [ 10,  22,  22,  22,  22,  22,  22,  22,  22,  22,  22,  22],
       [ 11,  11,  11,  11,  11,  11,  11,  11,  11,  11,  11,  11]])

Теперь вам, вероятно, нужно очистить результат, чтобы получить то, что вы хотите, но я все еще не уверен, было бы здорово, если бы вы моглиопубликовать ожидаемый результат.Примерно так должно поступить:

In [50]: [ row[:-s] for row,s in zip(csum,starts) ]
Out[50]: 
[array([  2,   6,  12,  20,  30,  42,  56,  72,  90, 110]),
 array([ 3,  8, 15, 24, 35, 48, 63, 80, 99]),
 array([ 4, 10, 18, 28, 40, 54, 70, 88]),
 array([ 5, 12, 21, 32, 45, 60, 77]),
 array([ 6, 14, 24, 36, 50, 66]),
 array([ 7, 16, 27, 40, 55]),
 array([ 8, 18, 30, 44]),
 array([ 9, 20, 33]),
 array([10, 22]),
 array([11])]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...