Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: is there an equivalent of diff(x) for dividing?

Tags:

r

diff

I am working with dataframes of financial data where I want to take the difference between rows, and also the "change" between rows. For the difference, the task is easy, simply:

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

My problem occurs when I want to have the change instead of the difference. That is, in each column of the data frame, I want to iteratively take the next element of the column divided by the previous and subtract one. My quick and dirty way of doing this is the following:

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

But I'm wondering if there is a function that would do this for me?

EDIT: small reproducible, as requested:

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

data

output from my own code snippet above (also what is expected):

output

like image 914
Helen Avatar asked Dec 24 '22 09:12

Helen


2 Answers

I don't know a base R function that does exactly this but there are different lag/lead functions in external packages. For example, you can use dplyr like this:

> 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

Compared to your own function:

> 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

You can put that in a custom function and use that:

f <- function(., n = 1L, default = NA) ./dplyr::lag(., n = n, default = default) -1
mutate_each(head(iris[-5]), funs(f))
like image 55
talat Avatar answered Dec 26 '22 22:12

talat


Here is an option with shift from 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
like image 30
akrun Avatar answered Dec 26 '22 22:12

akrun