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))
output from my own code snippet above (also what is expected):
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))
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With