2017-08-07 6 views
0

En utilisant la syntaxe dplyr, je suis à la recherche d'un moyen "élégant" pour mutate nouvelles variables à un cadre de données donné contenant des changements de pourcentage à travers différents points de temps.Comment puis-je calculer les changements en pourcentage de plusieurs variables et points temporels en même temps?

À titre d'exemple, tenez compte des data.frame variables contenant suivantes (var.a, var.b, var.c) prises à différents moments (A, B).

set.seed(123) 
df <- data.frame(replicate(6,sample(1:100,50,rep=TRUE))) 
names(df) <- c("A.var.a", "A.var.b", "A.var.c", 
       "B.var.a", "B.var.b", "B.var.c") 

Comment pourrais-je calculer les variations en pourcentage de A à B de chaque variable respective, et les mutate à la trame de données df? Je cherche un dplyr ou toute autre solution "intelligente" que je pourrais mettre en œuvre dans un cadre de données plus grand contenant plus de points de temps et de variables, en évitant de taper une nouvelle variable contenant la sortie désirée.

+1

Je pense que je connais la solution, mais me montrer s'il vous plaît quelques premières lignes de données de sortie – Adamm

Répondre

1

Vous pouvez ajouter tidy puis agréger chaque paire. Quelque chose comme

library(tidyverse) 
df %>% tibble::rowid_to_column() %>% 
    gather(key, value, -rowid) %>% 
    separate(key, c("time", "var"), extra = "merge") %>% # split "A.var.a" into "A" & "var.a" 
    arrange(rowid, var, time) %>% 
    group_by(rowid, var) %>% 
    summarise(diff = diff(value)/value[1]*100) %>% 
    spread(var, diff) 
# # A tibble: 50 x 4 
# # Groups: rowid [50] 
# rowid  var.a  var.b  var.c 
# * <int>  <dbl>  <dbl>  <dbl> 
# 1  1 193.103448 380.00000 -56.66667 
# 2  2 -36.708861 115.55556 -32.35294 
# 3  3 -4.878049 -23.75000 22.44898 
# 4  4 -71.910112 300.00000 -71.87500 
# 5  5 -87.368421 -28.07018 10.20408 
# 6  6 680.000000 323.80952 -12.22222 
# 7  7 9.433962 184.61538 -81.52174 
# 8  8 -75.555556 -61.84211 -32.78689 
# 9  9 -19.642857 -80.00000 14.28571 
# 10 10 -52.173913 -52.63158 480.00000 
# # ... with 40 more rows 

?

Pour ajouter les colonnes à vos données d'origine, vous pouvez ajouter %>% ungroup() %>% select(-rowid) %>% rename_all(~paste0("perc_", .x)) %>% bind_cols(df) aux lignes ci-dessus.

Ou essayez une approche rowwise dans les veines de

f <- function(x) { 
    as.list(diff(x, lag=3)/x[1:3]*100) 
} 
df %>% 
    rowwise %>% 
    do(data.frame(perc = f(unlist(.))) 
) %>% 
    bind_cols(df) 
# Source: local data frame [50 x 9] 
# Groups: <by row> 
# 
# # A tibble: 50 x 9 
# perc.B.var.a perc.B.var.b perc.B.var.c A.var.a A.var.b A.var.c B.var.a B.var.b B.var.c 
#   <dbl>  <dbl>  <dbl> <int> <int> <int> <int> <int> <int> 
# 1 193.103448 380.00000 -56.66667  29  5  60  85  24  26 
# 2 -36.708861 115.55556 -32.35294  79  45  34  50  97  23 
# 3 -4.878049 -23.75000  22.44898  41  80  49  39  61  60 
# 4 -71.910112 300.00000 -71.87500  89  13  96  25  52  27 
# 5 -87.368421 -28.07018  10.20408  95  57  49  12  41  54 
# 6 680.000000 323.80952 -12.22222  5  21  90  39  89  79 
# 7  9.433962 184.61538 -81.52174  53  13  92  58  37  17 
# 8 -75.555556 -61.84211 -32.78689  90  76  61  22  29  41 
# 9 -19.642857 -80.00000  14.28571  56  90  42  45  18  48 
# 10 -52.173913 -52.63158 480.00000  46  38  15  22  18  87 
# # ... with 40 more rows 

Les deux peuvent avoir besoin de quelques ajustements ...

+0

Où est-ce que la fonction 'rename_all' vient? paquet 'dplyr'? – AJMA

+0

@AJMA oui, c'est de 'dplyr'. – lukeA