Reputation: 141
I have a dataset that looks like this, where there are ~500 dataframes in a list:
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 2
Within each column, I want to find the ratio of the first value to the second value, then the third value to the fourth, then the fifth value to the six, etc. Then I want to do that to every column, and output it to a new data frame. Like this:
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
1 1 1 1 1 1 1 1 0.5
And I want to be able to apply it to the list of data frames at one time.
The closest I've gotten is with one data frame, and only one column... where I would also have to delete every other value (which is ok, I can do that in post processing).
ratio = df[[1]][,1]/lag(df[[1]][,1],1)
But again, it needs to do every column into the new data frame, applied to a list of data frames.
Note that the actual values can be anything from 0 to 2000, they are not necessarily all 1's and 2's.
data
df <- data.frame(cbind(1, 1, 1, 1, 1, 1, 1, 1, rep(1:2, 10)))
ll <- list(df, df, df)
Upvotes: 1
Views: 60
Reputation: 10761
We can use the apply
function, and work with the seq
function. The key is in what we're doing with the seq
function. The first one we're iterating from 1 to n by steps of 2 (1, 3, 5, ...), the next we're iterating from 2 to n by steps of 2 (2, 4, 6, ...). This might cause issues if your row count is not an even number.
apply(d, 2,
FUN = function(x) x[seq(1, length(x), by = 2)] / x[seq(2, length(x), by= 2)])
V1 V2 V3 V4 V5 V6 V7 V8 V9
[1,] 1 1 1 1 1 1 1 1 0.5
[2,] 1 1 1 1 1 1 1 1 0.5
[3,] 1 1 1 1 1 1 1 1 0.5
[4,] 1 1 1 1 1 1 1 1 0.5
[5,] 1 1 1 1 1 1 1 1 0.5
[6,] 1 1 1 1 1 1 1 1 0.5
[7,] 1 1 1 1 1 1 1 1 0.5
[8,] 1 1 1 1 1 1 1 1 0.5
[9,] 1 1 1 1 1 1 1 1 0.5
[10,] 1 1 1 1 1 1 1 1 0.5
Using the list you added to your question:
lapply(ll,
FUN = function(d)
apply(d, 2,
FUN =
function(x) x[seq(1, length(x), by = 2)] / x[seq(2, length(x), by= 2)]))
Upvotes: 2