#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