2016-02-04 1 views
2

Je travaille avec des données de données financières où je veux faire la différence entre les lignes, et aussi le "changement" entre les lignes. Pour la différence, la tâche est facile, il suffit:R: Y a-t-il un équivalent de diff (x) pour diviser?

apply(df, MARGIN=2, FUN=function(x) diff(x)) 

Mon problème se produit lorsque je veux avoir le changement au lieu de la différence. C'est-à-dire, dans chaque colonne de la trame de données, je veux itérativement prendre l'élément suivant de la colonne divisé par le précédent et soustraire un. Ma façon rapide et sale de le faire est la suivante:

apply(df, MARGIN=2, FUN=function(x) x[2:length(x)]/x[1:length(x)-1]-1) 

Mais je me demande s'il y a une fonction qui ferait cela pour moi?

EDIT: petit reproductible, tel que demandé:

données < -data.frame (c (1,2,4,15), c (2,1,5,8))

data

sortie de mon extrait de code ci-dessus (aussi ce qui est prévu):

output

Répondre

3

Je ne connais pas une fonction de base R qui fait exactement cela, mais il existe différentes fonctions lag/lead dans des packages externes. Par exemple, vous pouvez utiliser dplyr comme ceci:

> mutate_each(head(iris[-5]), funs(./lag(.)-1)) 
# Sepal.Length Sepal.Width Petal.Length Petal.Width 
#1   NA   NA   NA   NA 
#2 -0.03921569 -0.14285714 0.00000000   0 
#3 -0.04081633 0.06666667 -0.07142857   0 
#4 -0.02127660 -0.03125000 0.15384615   0 
#5 0.08695652 0.16129032 -0.06666667   0 
#6 0.08000000 0.08333333 0.21428571   1 

Par rapport à votre propre fonction:

> apply(head(iris[-5]), MARGIN=2, FUN=function(x) x[2:length(x)]/x[1:length(x)-1]-1) 
# Sepal.Length Sepal.Width Petal.Length Petal.Width 
#2 -0.03921569 -0.14285714 0.00000000   0 
#3 -0.04081633 0.06666667 -0.07142857   0 
#4 -0.02127660 -0.03125000 0.15384615   0 
#5 0.08695652 0.16129032 -0.06666667   0 
#6 0.08000000 0.08333333 0.21428571   1 

Vous pouvez le mettre dans une fonction personnalisée et l'utiliser:

f <- function(., n = 1L, default = NA) ./dplyr::lag(., n = n, default = default) -1 
mutate_each(head(iris[-5]), funs(f)) 
2

ici est une option avec shift à partir de data.table

library(data.table) 
as.data.table(head(iris))[, lapply(.SD, function(x) 
        x/shift(x)-1), .SDcols=1:4] 
# Sepal.Length Sepal.Width Petal.Length Petal.Width 
#1:   NA   NA   NA   NA 
#2: -0.03921569 -0.14285714 0.00000000   0 
#3: -0.04081633 0.06666667 -0.07142857   0 
#4: -0.02127660 -0.03125000 0.15384615   0 
#5: 0.08695652 0.16129032 -0.06666667   0 
#6: 0.08000000 0.08333333 0.21428571   1 
1

Voici quelques façons. Le premier renvoie une trame de données, le second une matrice et le dernier un objet zoo. Les deux premiers n'utilisent aucun paquet.

> data[-1,]/data[-nrow(data), ] - 1 
    c.1..2..4..15. c.2..1..5..8. 
2   1.00   -0.5 
3   1.00   4.0 
4   2.75   0.6 

> exp(diff(log(as.matrix(data)))) - 1 
    c.1..2..4..15. c.2..1..5..8. 
[1,]   1.00   -0.5 
[2,]   1.00   4.0 
[3,]   2.75   0.6 

> library(zoo) 
> diff(as.zoo(data), arithmetic = FALSE) - 1 
    c.1..2..4..15. c.2..1..5..8. 
2   1.00   -0.5 
3   1.00   4.0 
4   2.75   0.6 
+0

super propre, merci! – Erosennin