Вернуть сводную таблицу, которая суммирует данные с итерацией и оператором управления - PullRequest
2 голосов
/ 09 мая 2020

ни одна из этих функций не является особенно сложной, но мне интересно, как их объединить.

df <- tibble::tibble(index = seq(1:8),
                 amps = c(7, 6, 7, 0, 7, 6, 0, 6))

Пока есть положительное значение для ампер, я хотел бы их суммировать вверх. Если amps = 0, то это перерыв в последовательности, и я хотел бы вернуть 0, а затем начать заново. Я также хотел бы вернуть соответствующее значение индекса. Результат будет выглядеть так:

index  amps
<dbl> <dbl>
1     1    20
2     4     0
3     5    13
4     7     0
5     8     6

Я могу сделать это в VBA, но я хотел бы улучшить свои навыки R в функциональном программировании. Я бы предпочел использовать функции, а не циклы, просто потому, что они чище. Любая помощь приветствуется.

Ответы [ 4 ]

1 голос
/ 09 мая 2020

Другое базовое решение R с использованием rle + tapply

u <- with(rle(df$amps == 0), rep(seq_along(lengths), lengths))
dfout <- data.frame(
    index = which(!duplicated(u)),
    amps = tapply(df$amps, u, sum)
)

, что дает

> dfout
  index amps
1     1   20
2     4    0
3     5   13
4     7    0
5     8    6
0 голосов
/ 09 мая 2020

Мы можем создать новую группу, где amps = 0 или где предыдущее значение amps равно 0, получить первое значение index и sum из amps для каждой группы.

library(dplyr)

df %>%
  group_by(gr = cumsum(amps == 0 | lag(amps, default = first(amps)) == 0)) %>%
  summarise(index = first(index), amps = sum(amps)) %>%
  select(-gr)

# A tibble: 5 x 2
#  index  amps
#  <int> <dbl>
#1     1    20
#2     4     0
#3     5    13
#4     7     0
#5     8     6

Использование того же logi c in data.table:

library(data.table)

setDT(df)[, .(index = first(index), amps = sum(amps)), 
               cumsum(amps == 0 | shift(amps, fill = first(amps)) == 0)]
0 голосов
/ 09 мая 2020

В базе R мы можем использовать aggregate на основе rle.

ll <- rle(df$amps != 0)$lengths
rr <- aggregate(amps ~ cbind(index=rep(index[!!c(amps[1]>0, diff(amps!=0))], ll)), df, sum) 
rr
#   index amps
# 1     1   20
# 2     4    0
# 3     5   13
# 4     7    0
# 5     8    6
0 голосов
/ 09 мая 2020

Один dplyr вариант может быть:

df %>%
 group_by(grp = with(rle(amps == 0), rep(seq_along(lengths), lengths))) %>%
 summarise(index = first(index),
           amps = sum(amps))

    grp index  amps
  <int> <int> <dbl>
1     1     1    20
2     2     4     0
3     3     5    13
4     4     7     0
5     5     8     6
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...