R: совокупная сумма с условиями [дубликат]

Я поздний участник этого вопроса, но я хочу упомянуть здесь, что строка «Программа для интерфейса, а не реализация» имела хорошее обсуждение в книге шаблонов дизайна GoF (Gang of Four).

На стр. 18:

Программа для интерфейса, а не для реализации

Не объявляйте переменные экземплярами конкретных конкретных классов. Вместо этого зафиксируйте только интерфейс, определенный абстрактным классом. Вы найдете это общей темой шаблонов проектирования в этой книге.

и выше этого, это началось с:

Есть два преимущества манипулировать объектами исключительно с точки зрения интерфейса, определенного абстрактными классами:

  1. Клиенты не знают о конкретных типах объектов, которые они используют, если объекты соответствуют интерфейсу, который ожидают клиенты.
  2. Клиенты не знают о классах, которые реализуют эти объекты. Клиенты знают только об абстрактном классе (ов), определяющем интерфейс.

Так, другими словами, не записывайте его в свои классы, чтобы он имел метод quack() для уток, а затем метод bark() для собак, поскольку они слишком специфичны для конкретной реализации класса (или подкласса). Вместо этого напишите метод, используя имена, которые являются достаточно общими для использования в базовом классе, например giveSound() или move(), чтобы их можно было использовать для уток, собак или даже автомобилей, а затем для клиента вашего классы могут просто сказать .giveSound(), а не думать о том, использовать ли quack() или bark() или даже определить тип перед выдачей правильного сообщения, которое должно быть отправлено объекту.

2
задан TARehman 7 October 2015 в 13:54
поделиться

3 ответа

Вот один из способов с ave:

ave(df$a, cumsum(c(F, diff(df$a) < 0)), FUN=seq_along) - 1
 [1] 0 1 2 3 0 1 2 3 4 5 6 0 1 0

Мы можем получить текущее количество, сгруппированное по diff(df$a) < 0. Каковы позиции в векторе, которые меньше их предшественников. Мы добавим c(F, ..) для учета первой позиции. Суммарная сумма этого вектора создает индекс для группировки. Функция ave может выполнять функцию по этому индексу, мы используем seq_along для текущего подсчета. Но поскольку он начинается с 1, мы вычитаем один ave(...) - 1, чтобы начать с нуля.


Аналогичный подход с использованием dplyr:

library(dplyr)
df %>% 
  group_by(cumsum(c(FALSE, diff(a) < 0))) %>% 
  mutate(row_number() - 1)
11
ответ дан Pierre Lafortune 22 August 2018 в 18:28
поделиться
  • 1
    Или с помощью dplyr (в соответствии с тегом) df %>% group_by(cumsum(c(FALSE, diff(a) < 0))) %>% mutate(row_number() - 1) – David Arenburg 7 October 2015 в 13:59
  • 2
    Вау, спасибо. Работает на меня. Я продолжал пытаться сделать это с ave или rle, но не мог собрать его. – nsymms 7 October 2015 в 14:01
  • 3
    Спасибо @DavidArenburg. Добавлено:) Хотя я думаю, что тег был для наводящих целей, а не для требуемого метода. – Pierre Lafortune 7 October 2015 в 14:04
  • 4
    Да, я не женат на dplyr, я просто думал, что это логическое направление. Оба ответа выглядят великолепно. Я сделаю несколько тестов времени, чтобы увидеть, что лучше всего работает в моей ситуации. Еще раз спасибо; застряли на этом много часов со вчерашнего дня. – nsymms 7 October 2015 в 14:09
a <- c(1,2,3,4,2,3,4,5,8,9,10,1,2,1)
f <- c(0, diff(a)>0)
ifelse(f, cumsum(f), f)

, что он не перезагружен. с сбросом:

unlist(tapply(f, cumsum(c(0, diff(a) < 0)), cumsum))
2
ответ дан jogo 22 August 2018 в 18:28
поделиться

Вам не нужно dplyr:

fun <- function(x) {
  test <- diff(x) > 0
  y <- cumsum(test)
  c(0, y - cummax(y * !test))
}

fun(df$a)
[1] 0 1 2 3 0 1 2 3 4 5 6 0 1 0
6
ответ дан Roland 22 August 2018 в 18:28
поделиться
  • 1
    Я предпочитаю это, очень аккуратно. – Colonel Beauvel 7 October 2015 в 14:28
  • 2
    Я видел что-то подобное на SO, но больше не могу его найти. Я бы очень хотел дать должное. – Roland 7 October 2015 в 14:41
Другие вопросы по тегам:

Похожие вопросы: