Создание функции для выполнения условной суммы в R

#r

#r

Вопрос:

У меня есть фрейм данных, подобный этому:

 datlt;- data.frame (  'Ones'=c(0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0),   'Thats'=c(0,5,3,6,8,4,5,6,8,3,1,3,4,5,6,7,4,3,4,5))  

Я должен создать функцию (gap1), которая определяет каждый 1 в единицах и суммирует n-1, n и n 1 в этом, причем n находится в той же строке, что и 1.

Например, в этом наборе данных у меня есть два 1.

 datlt;- data.frame (  'Ones'=c(0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0),   'Thats'=c(0,5,3,6,8,4,5,6,8,3,1,3,4,5,6,7,4,3,4,5)) dat  

Это должно быть результатом:

 Ones Thats gap1  1 4 17 #(8 4 5)  1 1 7 #(3 1 3)  

Я хотел бы расширить этот пробел по своему желанию, например:

 Ones Thats gap1 gap2 gap3 ...  1 4 17 29 #(6 8 4 5 6)  1 1 7 9 #(8 3 1 3 4)    

Есть еще одна проблема, которую я должен рассмотреть: Предположим, у нас есть этот фрейм данных:

 datlt;- data.frame (  'Ones'=c(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0),   'Thats'=c(0,5,3,6,8,4,5,6,8,3,1,NA,4,5,6,7,4,3,4,5))  

В случае, если в начале (или в конце) есть 1, или если есть NA, функция должна использовать доступные данные.

В этом случае, например:

 Ones Thats gap1 gap2  1 0 5 (0 5) 8 #(0 5 3)  1 4 17 (8 4 5) 29 #(6 8 4 5 6)  1 1 4 (3 1 NA) 16 #(8 3 1 NA 4)      

У вас есть какой-нибудь совет?

Комментарии:

1. Что вы пробовали и где вы застряли?

Ответ №1:

С помощью tidyverse / collapse

Для произвольного числа лидов и лагов collapse пакет предлагает хорошую функцию flag , которая имеет дополнительные аргументы для указания столбцов ( cols ) или группирующих переменных g .

 library(dplyr) f lt;- function(df, n){  df %gt;%  collapse::flag(-n:n) %gt;%  transmute(Ones, Thats, gap = rowSums(., na.rm = T) - 1) %gt;%  filter(Ones == 1) }  x lt;- data.frame (  'Ones'=c(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0),   'Thats'=c(0,5,3,6,8,4,5,6,8,3,1,NA,4,5,6,7,4,3,4,5))  # we can now specify how many lags to count: f(x, 1)   Ones Thats gap 1 1 0 5 2 1 4 17 3 1 1 4 f(x, 2)  Ones Thats gap 1 1 0 8 2 1 4 29 3 1 1 16  

Или, если вы хотите указать количество пробелов для вычисления, мы можем упростить функцию до

 f lt;- function(df, n){  df %gt;%  collapse::flag(-n:n) %gt;%  rowSums(na.rm = T) - 1 }  x %gt;%  mutate(gap1 = f(., 1),  gap2 = f(., 2)) %gt;%  filter(Ones == 1)  Ones Thats gap1 gap2 1 1 0 5 8 2 1 4 17 29 3 1 1 4 16  

Основание R Если вам нравятся краткие функции:

 f lt;- Vectorize((df, n) rowSums(collapse::flag(df, -n:n), na.rm = T) - 1, "n") x[paste0("gap", 1:2)] lt;- f(x, 1:2) ; subset(x, Ones == 1)  Ones Thats gap1 gap2 1 1 0 5 8 6 1 4 17 29 11 1 1 4 16  

Ответ №2:

С BaseR ,

 myfun lt;- function(data,gap=1) {   points lt;- which(data["Ones"]==1)  sapply(points, function(x) {   bottom lt;- ifelse(x-gaplt;=0,1,x -gap)   top lt;- ifelse(x  gap gt; nrow(data),nrow(data),x  gap)   sum(data[bottom:top,"Thats"], na.rm=T)  })  }  #gt; myfun(dat,1) #[1] 5 17 4 #gt; myfun(dat,2) #[1] 8 29 16  

Ответ №3:

Другое базовое решение R

 f lt;- function(dat, width = 1) {  dat$gaps lt;- sapply(seq(nrow(dat)), function(x) {  if(dat$Ones[x] == 0) return(0)  i lt;- x   seq(2 * width   1) - (width   1)  i lt;- i[i gt; 0]  i lt;- i[i lt; nrow(dat)]  sum(dat$Thats[i])  })  dat[dat$Ones == 1,] }  f(dat, 1) #gt; Ones Thats gaps #gt; 6 1 4 17 #gt; 11 1 1 7  f(dat, 2) #gt; Ones Thats gaps #gt; 6 1 4 29 #gt; 11 1 1 19