R功能滚动分区

时间:2018-01-26 18:18:15

标签: r

我可以对矢量执行滚动划分,我可以获取数据,然后滞后相同的数据并执行除法:

# Dummy Data
sample <- c(4,5,6,7,8,4,2,6,5,4,3,2,1,2,3,4,5,6)
lagSam <- lag(sample) # Lag by 1
output <- sample / lagSam # Perform division
sample.df <- data.frame(sample, desired = output)

with the desired output: 
   sample   desired
1       4        NA
2       5 1.2500000
3       6 1.2000000
4       7 1.1666667
5       8 1.1428571
6       4 0.5000000
7       2 0.5000000
8       6 3.0000000
9       5 0.8333333
10      4 0.8000000
11      3 0.7500000
12      2 0.6666667
13      1 0.5000000
14      2 2.0000000
15      3 1.5000000
16      4 1.3333333
17      5 1.2500000
18      6 1.2000000

我的问题是,我如何在数据框架上做同样的事情?我有超过100列,需要对每个列进行滚动划分。我正在尝试编写一个函数并使用roll apply:

# My attempt 
division <- function(x) {
  #tail(x,1) / head(x,1)
  x / lag(x)
}

rollapplyr(sample.df$sample, 1, division, fill = NA)

我试图用头部和尾部滞后,然后再次使用x /滞后x。

两种结果都会产生NA。

2 个答案:

答案 0 :(得分:2)

我经常发现我想要dplyr::lag行为,但当stats::lag返回类似tsp的对象时,我会感到吃惊。

您已关闭tail/head功能。使用否定n

  n: a single integer. If positive, size for the resulting object:
      number of elements for a vector (including lists), rows for a
      matrix or data frame or lines for a function. If negative,
      all but the 'n' last/first number of elements of 'x'.
c(NA, tail(sample.df$sample,n=-1) / head(sample.df$sample,n=-1))
#  [1]        NA 1.2500000 1.2000000 1.1666667 1.1428571 0.5000000 0.5000000
#  [8] 3.0000000 0.8333333 0.8000000 0.7500000 0.6666667 0.5000000 2.0000000
# [15] 1.5000000 1.3333333 1.2500000 1.2000000

请注意,您执行滚动应用的想法稍有问题,因为它会将数字除以前一个除法的结果,而不是之前的值。也就是说,一个滚动的鸿沟中的c(2,3,4)应该以一个初始值(比如1,即分区身份)开始,然后选择c(2/1, 3/(2/1), 4/(3/(2/1))),而不是(我认为)你要求了。

这使得该功能成为:

division <- function(x) c(NA, tail(x,n=-1) / head(x,n=-1))

那么你可以做到

lapply(sample.df, division)

如果您只想在选择列上运行此功能,请执行

ind <- 1
lapply(sample.df[ind], division)
# $sample
#  [1]        NA 1.2500000 1.2000000 1.1666667 1.1428571 0.5000000 0.5000000
#  [8] 3.0000000 0.8333333 0.8000000 0.7500000 0.6666667 0.5000000 2.0000000
# [15] 1.5000000 1.3333333 1.2500000 1.2000000
cbind(sample.df, lapply(sample.df[ind], division))
#    sample desired    sample
# 1       4       1        NA
# 2       5       1 1.2500000
# 3       6       1 1.2000000
# 4       7       1 1.1666667
# 5       8       1 1.1428571
# 6       4       1 0.5000000
# 7       2       1 0.5000000
# 8       6       1 3.0000000
# 9       5       1 0.8333333
# 10      4       1 0.8000000
# 11      3       1 0.7500000
# 12      2       1 0.6666667
# 13      1       1 0.5000000
# 14      2       1 2.0000000
# 15      3       1 1.5000000
# 16      4       1 1.3333333
# 17      5       1 1.2500000
# 18      6       1 1.2000000

这当然会产生一个重复的名称,但这只是一个开始。

BTW:滚动通常与向量上的累积过程有关。您正在寻找的是单独为每个向量应用一个函数并捕获响应。

答案 1 :(得分:1)

以下是一些方法:

1)差异

transform(sample.df, desired = c(NA, exp(diff(log(sample)))))
##    sample   desired
## 1       4        NA
## 2       5 1.2500000
## 3       6 1.2000000
## 4       7 1.1666667
## 5       8 1.1428571
## ... etc ...

使用内置数据框anscombe

将其应用于多个列
rbind(NA, exp(diff(log(as.matrix(anscombe)))))

2)diff.zoo

library(zoo)

z <- zoo(sample.df$sample)
merge(z, desired = diff(z, arith = FALSE), all = TRUE)
##    z   desired
## 1  4        NA
## 2  5 1.2500000
## 3  6 1.2000000
## 4  7 1.1666667
## 5  8 1.1428571
## ... etc ...

将其应用于anscombe的所有列:

z <- zoo(rbind(NA, anscombe))
diff(z, arith = FALSE)

3)dplyr

library(dplyr)

sample.df %>% mutate(desired = sample/lag(sample))
##    sample   desired
## 1       4        NA
## 2       5 1.2500000
## 3       6 1.2000000
## 4       7 1.1666667
## 5       8 1.1428571
## ... etc ...

将其应用于anscombe的所有列:

anscombe %>% mutate_all(funs(. / lag(.)))

4)rollapplyr

library(zoo)

transform(sample.df, desired = rollapplyr(sample, 2, function(x) x[2]/x[1], fill = NA))
##    sample   desired
## 1       4        NA
## 2       5 1.2500000
## 3       6 1.2000000
## 4       7 1.1666667
## 5       8 1.1428571

将其应用于anscombe的所有列:

rollapplyr(anscombe, 2, function(x) x[2]/x[1], fill = NA))

5)lag.ts

transform(sample.df, desired = c(NA, lag(ts(sample)) / ts(sample)))
##    sample   desired
## 1       4        NA
## 2       5 1.2500000
## 3       6 1.2000000
## 4       7 1.1666667
## 5       8 1.1428571

要将其应用于anscombe的所有列,请使用以下内容。请注意,不应该加载dplyr,因为它使用自己的lag令人讨厌lag。或者使用stats::lag

lag(ts(anscombe)) / ts(anscombe)