2017-07-07 70 views
2

說我有一個data.frame看起來像下面:add_row並做一些計算

df <- data.frame(group = c("group1","group1", "group2", "group2"), 
       year = c(2000, 2001, 2000, 2001), 
       value = c(10, 13, 2, 5)) 

我想組各組,再加入一排,然後做3列的計算。因此,例如,新的數據幀是這樣的(計算只是value(-1)+value(-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將會很棒!

此外,我希望能夠做到這一點在未來的十個時期,所以今年將是從最終數據框架2000年到2011年的序列。

回答

3

這是一種類似斐波那契的計算,用for循環很容易編寫,與矢量化操作不太相關。 for循環在R中應該謹慎使用,因爲不正確地使用它們會使代碼非常慢,但是如果事先通過擴展您的數據框預先分配內存,則可以使用tidyr::complete預先分配內存:

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 

如果要避免循環和向量化,請使用Fibonacci序列的公式表達式。從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編譯for循環的),還有兩者之間幾乎沒有時間差。基準是棘手的,因爲系列趨於超過.Machine$double.xmax和在大約第一千四百七十五術語轉向Inf,但複製在新的輸入到1475000次的計算與每個方法,

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 
+0

我用一個簡化的例子進行計算 - 的實際計算更爲複雜。它需要使用前一時期的增長作爲未來價值的預測指標。但是完成的功能是什麼(加上循環)作爲一些部分是歷史和一些預測,我想保留歷史 - 如果任何有意義的 –