Я хочу написать код для подсчета и суммирования любых положительных и отрицательных серий чисел.
Числа либо положительные, либо отрицательные (без нуля).
Я написал коды с for
петлями. Есть ли творческая альтернатива?
Данные
р
set.seed(100)
x <- round(rnorm(20, sd = 0.02), 3)
питон
x = [-0.01, 0.003, -0.002, 0.018, 0.002, 0.006, -0.012, 0.014, -0.017, -0.007,
0.002, 0.002, -0.004, 0.015, 0.002, -0.001, -0.008, 0.01, -0.018, 0.046]
петли
р
sign_indicator <- ifelse(x > 0, 1,-1)
number_of_sequence <- rep(NA, 20)
n <- 1
for (i in 2:20) {
if (sign_indicator[i] == sign_indicator[i - 1]) {
n <- n + 1
} else{
n <- 1
}
number_of_sequence[i] <- n
}
number_of_sequence[1] <- 1
#############################
summation <- rep(NA, 20)
for (i in 1:20) {
summation[i] <- sum(x[i:(i + 1 - number_of_sequence[i])])
}
питон
sign_indicator = [1 if i > 0 else -1 for i in X]
number_of_sequence = [1]
N = 1
for i in range(1, len(sign_indicator)):
if sign_indicator[i] == sign_indicator[i - 1]:
N += 1
else:
N = 1
number_of_sequence.append(N)
#############################
summation = []
for i in range(len(X)):
if number_of_sequence[i] == 1:
summation.append(X[i])
else:
summation.append(sum(X[(i + 1 - number_of_sequence[i]):(i + 1)]))
результат
x n_of_sequence sum
1 -0.010 1 -0.010
2 0.003 1 0.003
3 -0.002 1 -0.002
4 0.018 1 0.018
5 0.002 2 0.020
6 0.006 3 0.026
7 -0.012 1 -0.012
8 0.014 1 0.014
9 -0.017 1 -0.017
10 -0.007 2 -0.024
11 0.002 1 0.002
12 0.002 2 0.004
13 -0.004 1 -0.004
14 0.015 1 0.015
15 0.002 2 0.017
16 -0.001 1 -0.001
17 -0.008 2 -0.009
18 0.010 1 0.010
19 -0.018 1 -0.018
20 0.046 1 0.046
n_of_sequence
не совпадает с желаемымВы можете рассчитать длину пробега каждого знака, используя
rle
отbase
и сделать что-то вроде этого.Получить
n_of_sequence
Наконец, чтобы получить суммы последовательностей,
источник
Вот простая нецикличная функция в R:
Так что вы можете сделать:
Создано 2020-02-16 пакетом представлением (v0.3.0)
источник
Вот простое
tidyverse
решение ...источник
Что касается Python, кто-то придумает решение с использованием библиотеки панд. А пока вот простое предложение:
Вывод:
Если вам нужны отдельные списки, вы можете сделать
или, если итераторы в порядке, просто
(объяснение здесь )
источник
Два разных ленивых решения в Python, использующих модуль itertools .
Используя itertools.groupby (и накапливать)
Использование itertools.accumulate с пользовательской функцией накопления
initial
Ключевое слово аргумент был добавлен в Python 3.8. В более ранних версиях вы можете использоватьitertools.chain
для добавления (0,0) -тупы:Результат такой, как и ожидалось:
источник
Я рекомендую R пакет бегун для этого вида операций. streak_run вычисляет последовательное вхождение одного и того же значения, а sum_run вычисляет сумму в окне, длина которой определяется
k
аргументом.Вот решение:
Ниже ориентир для сравнения актуальных решений
источник
df <- data.table(x)
полная копия данных. Кроме того, вы печатаете данные в некоторых примерах (это еще одна полная копия), а в других - нет.r = runner_streak(x); d = dt_streak(dt) ; all.equal(r, d$sum)
. Только проверил несколько bbuttv_streak
дает так же, какdt_streak
;count_and_sum
дает то же,runner_streak
что отличается от предыдущих двух.В R вы также можете сделать:
источник
Киньте мой [r] ответ в шапку, оптимизированный для скорости и работающий с любой длиной x (в отличие от ответа автора, который был жестко запрограммирован для длины 20):
И, чтобы сравнить время выполнения на моем текущем (очень медленном) рабочем компьютере, вот вывод моего микробенчмарка, использующего все решения R в этом потоке. Неудивительно, что решения, делающие наибольшее количество копий и конверсий, были медленнее.
-------------- РЕДАКТИРОВАТЬ -------------- @nicola указала, что мое решение не самое быстрое для длинных длин x, что должно быть довольно очевидно, так как я постоянно делаю копии векторов, используя вызовы типа x <- c (x, y). Я только создал самое быстрое решение для длин и 20 и просто использовал микробенчмарки настолько низко, насколько мог.
Чтобы сделать более справедливое сравнение, я отредактировал все версии, чтобы сгенерировать оригинальный код так, как я считаю, будет самым быстрым, но я приветствую отзывы об этом. Вот мой полный код тестирования и результаты для моей очень медленной системы. Я приветствую любые отзывы.
Как показывают эти результаты, для других длин, чем я оптимизировал, моя версия медленная. Чем длиннее «х», тем медленнее он становится смехотворно медленным на всем, что выше 1000. Моя любимая версия - «Ронак», которая только вторая по скорости в моей системе. GoGonzo является самым быстрым на моей машине на этих длинных длинах.
источник
data.table
решения @ Ronak, ваша длина на порядок медленнее для длины ~ 100000.В Python, помимо определения класса для хранения переменных памяти, вы можете использовать замыкание для достижения того же.
Обратите внимание, что это работает только для Python 3 (в Python 2 я думаю, что вы не можете изменить переменную замыкания следующим образом). Аналогичная вещь для суммирования.
источник
Я думаю, что цикл будет легче читать, но просто для удовольствия, вот решение на Python с использованием рекурсии:
источник
Вот еще один базовый подход R:
источник
Reduce
скрывает петлю, так что это не зацикленное решение.Простой ответ Python, игнорирует регистр 0:
Немного более сложное решение, также заботится о 0 случае:
источник