假设我有一个如下所示的 data.frame:
df <- data.frame(group = c("group1","group1", "group2", "group2"),
year = c(2000, 2001, 2000, 2001),
value = c(10, 13, 2, 5))
我想按每个组分组,然后添加一行,然后对第 3 列进行计算。因此,例如,新数据框看起来像这样(计算只是 value(-1) +值(-2)
)
df <- data.frame(group = c("group1","group1", "group1", "group2", "group2", "group2"),
year = c(2000, 2001, 2002, 2000, 2001, 2002),
value = c(10, 13, 23, 2, 5, 7))
我试过使用 dplyr,但我似乎无法弄明白。所以我对任何解决方案都持开放态度,尽管如果有一个 dplyr 解决方案那就太好了!
此外,我希望能够将这十个时期计算到 future ,因此年份将是最终 data.frame 中从 2000 年到 2011 年的序列。
最佳答案
这是一种类似于斐波那契的计算,使用 for
循环编写起来非常简单,而使用矢量化操作就没那么简单了。在 R 中应谨慎使用 for
循环,因为不正确地使用它们会使您的代码慢得惊人,但是如果您通过使用 tidyr::complete
扩展 data.frame 来预分配内存> 事先,您可以编写一个函数来轻松包含循环:
library(tidyverse)
df <- data.frame(group = c("group1","group1", "group2", "group2"),
year = c(2000, 2001, 2000, 2001),
value = c(10, 13, 2, 5))
fibonacci <- function(x){
for(i in seq(3, length(x))){
x[i] <- x[i-1] + x[i-2]
}
x
}
df2 <- df %>%
group_by(group) %>%
complete(year = 2000:2005) %>%
mutate(value = fibonacci(value))
df2
#> # A tibble: 12 x 3
#> # Groups: group [2]
#> group year value
#> <fctr> <dbl> <dbl>
#> 1 group1 2000 10
#> 2 group1 2001 13
#> 3 group1 2002 23
#> 4 group1 2003 36
#> 5 group1 2004 59
#> 6 group1 2005 95
#> 7 group2 2000 2
#> 8 group2 2001 5
#> 9 group2 2002 7
#> 10 group2 2003 12
#> 11 group2 2004 19
#> 12 group2 2005 31
如果您想避免循环和矢量化,请使用斐波那契数列的公式表达式。来自 Wikipedia ,
fibonacci2 <- function(u0, u1, n){
phi <- (1 + sqrt(5)) / 2
psi <- 1 - phi
a <- (u1 - u0 * psi) / sqrt(5)
b <- (u0 * phi - u1) / sqrt(5)
a * phi^n + b * psi^n
}
df3 <- df %>%
group_by(group) %>%
complete(year = 2000:2005) %>%
mutate(value = fibonacci2(value[1], value[2], seq.int(0L, length(value) - 1)))
df3
#> # A tibble: 12 x 3
#> # Groups: group [2]
#> group year value
#> <fctr> <dbl> <dbl>
#> 1 group1 2000 10
#> 2 group1 2001 13
#> 3 group1 2002 23
#> 4 group1 2003 36
#> 5 group1 2004 59
#> 6 group1 2005 95
#> 7 group2 2000 2
#> 8 group2 2001 5
#> 9 group2 2002 7
#> 10 group2 2003 12
#> 11 group2 2004 19
#> 12 group2 2005 31
有些奇怪(可能是由于适当的预分配和 R 为循环添加的 JIT 编译),两者之间几乎没有时间差异。基准测试很棘手,因为该系列往往会超过 .Machine$double.xmax
并在大约第 1475 项时转向 Inf
,但每个方法都会在新输入上复制到 1,475,000 次计算,
microbenchmark::microbenchmark(
fibonacci = replicate(1000, {
x <- double(1475);
x[1:2] <- rnorm(2);
fibonacci(x)
}),
fibonacci2 = replicate(1000, {
x <- double(1475);
x[1:2] <- rnorm(2);
fibonacci2(x[1], x[2], seq.int(0L, length(x) - 1L))
})
)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> fibonacci 249.4110 255.9866 264.2625 261.6491 272.0018 295.3266 100
#> fibonacci2 202.3588 209.0647 219.0509 214.2429 223.5476 375.7604 100
关于r - add_row 并做一些计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44961933/