2015-07-11 8 views
13

Ich habe einen Datenrahmen mit einer ID-Spalte, eine Datumsspalte (12 Monate für jede ID), und ich habe 23 numerische Variablen. Ich möchte die prozentuale Veränderung nach Monat innerhalb jeder ID erhalten. Ich verwende das quantmod-Paket, um die prozentuale Änderung zu erhalten. HierWie kann ich die prozentuale Änderung innerhalb einer Gruppe für mehrere Spalten in R berechnen?

ist ein Beispiel mit nur drei Säulen (der Einfachheit halber):

ID Date V1 V2 V3 
1 Jan 2 3 5 
1 Feb 3 4 6 
1 Mar 7 8 9 
2 Jan 1 1 1 
2 Feb 2 3 4 
2 Mar 7 8 8 

Ich versuchte dplyr und die summarise_each Funktion zu nutzen, aber das war nicht erfolgreich. Genauer gesagt, habe ich versucht, die folgenden (Zug der Name des Datensatzes ist):

library(dplyr) 
library(quantmod) 

group1<-group_by(train,EXAMID) 

foo<-function(x){ 
    return(Delt(x)) 
} 

summarise_each(group1,funs(foo)) 

ich auch versucht, die tun Funktion in dplyr zu verwenden, aber ich war mit dem nicht erfolgreich entweder (eine schlechte Nacht, die ich mit vermuten!).

Ich denke, dass das Problem die Delt-Funktion ist. Als ich Delt mit der Summenfunktion ersetzen:

foo<-function(x){ 
     return(sum(x)) 
    } 
summarise_each(group1,funs(foo)) 

Das Ergebnis ist, dass jede Variable für jede ID über das Datum summiert wird. Wie kann sich der prozentuale Anteil für jede ID im Monatsvergleich ändern?

Antwort

9

Wie wäre es mit pct <- function(x) x/lag(x)? z.B.

pct(1:3) 
[1] NA 2.0 1.5 

Edit: Vorschlag Frank Hinzufügen

pct <- function(x) {x/lag(x)} 

dt %>% group_by(ID) %>% mutate_each(funs(pct), c(V1, V2, V3)) 

ID Date  V1  V2 V3 
1 Jan  NA  NA NA 
1 Feb 1.500000 1.333333 1.2 
1 Mar 2.333333 2.000000 1.5 
2 Jan  NA  NA NA 
2 Feb 2.000000 3.000000 4.0 
2 Mar 3.500000 2.666667 2.0 
+0

bekomme ich folgende Fehlermeldung: Fehler: einen einzelnen Wert , dass, obwohl eine sehr gute Idee ist zu erwarten. – mmmmmmmmmm

+4

@cwh_UCF Verwenden Sie muate anstelle von summarize (das einen einzelnen Wert zurückgeben soll): 'DF%>% group_by (ID)%>% mutate_each (Spaß (pct), c (V1, V2, V3))' – Frank

+0

@ Frank sollte das nicht eine Antwort, sondern eine Antwort sein. Fragen Sie einfach :) –

9

Das Problem, das Sie in laufen ist, weil Ihre Daten nicht in einer "ordentlich" Art und Weise formatiert ist. Sie haben Beobachtungen (V1: V3), die in Spalten sind und einen "breiten" Datenrahmen erzeugen. Der "Tidyverse" funktioniert am besten mit einem langen Format. Die gute Nachricht ist mit der gather() Funktion können Sie genau das bekommen, was Sie brauchen. Hier ist eine Lösung mit dem "Ordyverse".


library(tidyverse) 

# Recreate data set 
df <- tribble(
    ~ID, ~Date, ~V1, ~V2, ~V3, 
    1, "Jan", 2, 3, 5, 
    1, "Feb", 3, 4, 6, 
    1, "Mar", 7, 8, 9, 
    2, "Jan", 1, 1, 1, 
    2, "Feb", 2, 3, 4, 
    2, "Mar", 7, 8, 8 
) 
df 
#> # A tibble: 6 × 5 
#>  ID Date V1 V2 V3 
#> <dbl> <chr> <dbl> <dbl> <dbl> 
#> 1  1 Jan  2  3  5 
#> 2  1 Feb  3  4  6 
#> 3  1 Mar  7  8  9 
#> 4  2 Jan  1  1  1 
#> 5  2 Feb  2  3  4 
#> 6  2 Mar  7  8  8 

# Gather and calculate percent change 
df %>% 
    gather(key = key, value = value, V1:V3) %>% 
    group_by(ID, key) %>% 
    mutate(lag = lag(value)) %>% 
    mutate(pct.change = (value - lag)/lag) 
#> Source: local data frame [18 x 6] 
#> Groups: ID, key [6] 
#> 
#>  ID Date key value lag pct.change 
#> <dbl> <chr> <chr> <dbl> <dbl>  <dbl> 
#> 1  1 Jan V1  2 NA   NA 
#> 2  1 Feb V1  3  2 0.5000000 
#> 3  1 Mar V1  7  3 1.3333333 
#> 4  2 Jan V1  1 NA   NA 
#> 5  2 Feb V1  2  1 1.0000000 
#> 6  2 Mar V1  7  2 2.5000000 
#> 7  1 Jan V2  3 NA   NA 
#> 8  1 Feb V2  4  3 0.3333333 
#> 9  1 Mar V2  8  4 1.0000000 
#> 10  2 Jan V2  1 NA   NA 
#> 11  2 Feb V2  3  1 2.0000000 
#> 12  2 Mar V2  8  3 1.6666667 
#> 13  1 Jan V3  5 NA   NA 
#> 14  1 Feb V3  6  5 0.2000000 
#> 15  1 Mar V3  9  6 0.5000000 
#> 16  2 Jan V3  1 NA   NA 
#> 17  2 Feb V3  4  1 3.0000000 
#> 18  2 Mar V3  8  4 1.0000000 
+0

Dies sollte völlig die sein akzeptierte Antwort, fwiw. – d8aninja