2013-03-17 2 views
11

Я чувствую, что это довольно простой вопрос, но для жизни меня я не могу найти ответ. У меня довольно стандартный фреймворк данных, и то, что я пытаюсь сделать, это суммирование столбца значений до тех пор, пока они не достигнут некоторого значения (либо точного значения, либо больше его), после чего он упадет 1 в новый столбец (помечен удерживайте) и перезагружает суммирование в 0.Совокупная сумма до достижения максимума, затем повторите с нуля в следующей строке

У меня есть столбец минут, разница между минутами, колонкой keep и столбец общей суммы (пример, который я использую, намного чище, чем фактический полный набор данных)

minutes  difference  keep  difference_sum 
1052991158  0   0   0 
1052991338  180   0   180 
1052991518  180   0   360 
1052991698  180   0   540 
1052991878  180   0   720 
1052992058  180   0   900 
1052992238  180   0   1080 
1052992418  180   0   1260 
1052992598  180   0   1440 
1052992778  180   0   1620 
1052992958  180   0   1800 

разница сумма столбец был рассчитан с кодом

caribou.sub$difference_sum<-cumsum(difference) 

Что я хотел бы сделать, это запустить приведенный выше код с условием, что, когда суммарное значение достигает либо 1470, либо любого числа, большего, чем это, он помещает 1 в колонку сохранения, а затем перезапускает суммирование после этого и продолжает работать на протяжении всего набор данных.

Заранее спасибо, и если вам нужна дополнительная информация, дайте мне знать.

Ayden

+3

Сбрасывается ли 'difference_sum' в 0 при достижении 1470? Немного более длинный примерный набор, включающий, когда 'difference_sum' пересекает порог, поможет. – alexwhan

+0

Нет, это то, что я пытаюсь сделать, столбец суммы разницы в настоящее время вычисляется с помощью кода caribou.sub $ difference_sum <-cumsum (разница). Он просто продолжает идти и проходит весь путь через набор данных. – HeidelbergSlide

+0

Хорошо, но после того, как вы перешли порог, как вы собираетесь вычислять следующий порог? Используете ли вы излишек за 1470 или начинаете с 0 из следующего ряда? – alexwhan

ответ

7

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

current.sum <- 0 
for (c in 1:nrow(caribou.sub)) { 
    current.sum <- current.sum + caribou.sub[c, "difference"] 
    carribou.sub[c, "difference_sum"] <- current.sum 
    if (current.sum >= 1470) { 
     caribou.sub[c, "keep"] <- 1 
     current.sum <- 0 
    } 
} 

Не стесняйтесь прокомментировать, если это не совсем то, что вы хотите. Но, как указано alexwhan, ваше описание не совсем ясно.

+0

Ах, отлично, да, это точно. Все, что мне нужно было сделать, это скопировать и вставить, и вот оно. Огромное спасибо. – HeidelbergSlide

+0

Первая строка - 180. Должно быть 0? – Aaron

+0

В примере? Это должно быть 0, я только что изменил это. – HeidelbergSlide

7

Если предположить, что data.frame является df:

df$difference_sum <- c(0, head(cumsum(df$difference), -1)) 
# get length of 0's (first keep value gives the actual length) 
len <- sum(df$difference_sum %/% 1470 == 0) 
df$keep <- (seq_len(nrow(df))-1) %/% len 
df <- transform(df, difference_sum = ave(difference, keep, 
      FUN=function(x) c(0, head(cumsum(x), -1)))) 

#  minutes difference keep difference_sum 
# 1 1052991158  180 0    0 
# 2 1052991338  180 0   180 
# 3 1052991518  180 0   360 
# 4 1052991698  180 0   540 
# 5 1052991878  180 0   720 
# 6 1052992058  180 0   900 
# 7 1052992238  180 0   1080 
# 8 1052992418  180 0   1260 
# 9 1052992598  180 0   1440 
# 10 1052992778  180 1    0 
# 11 1052992958  180 1   180 
+2

Это именно то место, где я собирался[email protected] - это будет заметно быстрее, чем цикл – alexwhan

+0

Здесь нет «повторения с нуля». Он отклонится от другого ответа. –

+0

@MatthewLundberg, вы имеете в виду, что операционная система заинтересована в правильных значениях cumsum? Я думал, что нужно просто вычислить 'keep'? – Arun

1

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

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

df$difference_sum <- cumsum(df$difference) 
step <- (df$difference_sum %/% 1470) + 1 
k <- which(diff(step) > 0) + 1 
df$keep <- 0 
df$keep[k] <- 1 
step[k] <- step[k] - 1 
df$difference_sum <- df$difference_sum - c(0, df$difference_sum[k])[step] 
+0

Это действительно близко, но потому что (как я понимаю это, и я могу быть очень не прав) вы используете cumsum всего столбца разницы, избыток от предыдущего выбора включен в следующий выбор, так что это происходит и в одной строке скоро (первое выбранное значение находится на минуте 1620, но это оставляет 150 минут, которые следует игнорировать, но они используются для следующего выбора, поэтому следующий выбор происходит в минуту 1440 (потому что cumsum говорит, что на 150 минут больше, чем на самом деле)) , Имеет ли это смысл? Спасибо за помощь! – HeidelbergSlide

+0

О, я вижу. Да, я думаю, что это правильно (это означает, что мой ответ не совсем прав). Опять же, больший пример с желаемым выходом будет очень полезен, хотя кажется, что проблема решена, поэтому на данный момент не стоит беспокоиться. – Aaron

Смежные вопросы