Превращение линейной последовательности в массиве numpy в последовательность геометрической прогрессии - PullRequest
1 голос
/ 09 ноября 2019

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

  • новое первое значение = исходное первое значение

  • новое второе значение = суммаисходных значений два и три

  • новое третье значение = сумма исходных значений от четырех до семи

  • новое четвертое значение = суммазначений от восьми до пятнадцати

Конечно, я могу сделать это, просматривая данные, но мне нужно, чтобы эта обработка была выполнена как можно быстрее - массивы огромны. Какой самый быстрый способ сделать это?

пример:

12.0, 3.4, 9.2, 7.7, 4.9, 3.8, 6.9

должен стать:

12.0, 12.6, 23.3

Ответы [ 3 ]

2 голосов
/ 09 ноября 2019

Вы можете использовать np.add.reduceat и int.bit_length.

Пример:

# make example sequence
a = np.arange(100.0)

# form sums
np.add.reduceat(a,(1<<np.arange(a.size.bit_length()))-1)
# array([   0.,    3.,   18.,   84.,  360., 1488., 2997.])

Это добавляет элементы 0;1 + 2;3 + 4 + 5 + 6;и т. д., что показывает ваш пример, это то, что вы действительно хотите.

1 голос
/ 09 ноября 2019
seq = [12.0, 3.4, 9.2, 7.7, 4.9, 3.8, 6.9]

r = 0       # this is the binary power (2^r)
g_seq = []  # list to contain your final answer
i = 0       # index of start position for summing at each iteration  

while i < len(seq):   # once i reaches the last element, stop looping
    n = 2**r          # number of elements to sum in each iteration
    j = i + n         # index of end position for summing
    r+= 1             # increment power for next iteration
    subseq = seq[i:j] # slice of your input sequence to be summed
    g_seq.append(sum(subseq))   # sum the slice and append to answer list
    i = j             # j becomes the i for the next iteration

print(g_seq)
--------------------
[12.0, 12.6, 23.300000000000004]

Редактировать: добавлены комментарии

1 голос
/ 09 ноября 2019
from math import log, floor
a = [12.0, 3.4, 9.2, 7.7, 4.9, 3.8, 6.9]
print([sum(a[2**i-1:2**(i+1)-1]) for i in range(floor(log(len(a), 2)) + 1)])

Это выводит:

[12.0, 12.6, 23.3]

Индексы, используемые для сумм:

[(0, 1), (1, 3), (3, 7), (7, 15), (15, 31), ...]

Последняя сумма может быть сокращена, если длина списка неточнее одного меньше, чем степень 2.

...