ConanG
ConanG

Reputation: 749

Ratio of elements of vectors, in a list of vectors

I have a data frame which has a column:

> head(df$lengths,5)
[[1]]
[1] "28"

[[2]]
[1] "33"

[[3]]
[1] "47" "37" "42" "41"

[[4]]
[1] "41" "39" "64" "54"

[[5]]
[1] "45" "22" "23"

I would like to operate on the elements in the vectors, to obtain the ratios of the element(i) to the element(i-k) in each vector. Where a ratio cannot be obtained because element(i-k) has invalid index, the result should be NA. The desired output is like this, where I specified k=1:

[[1]]
[1] NA

[[2]]
[1] NA

[[3]]
[1] NA (37/47) (42/37) (41/42)

[[4]]
[1] NA (39/41) (64/39) (54/64)

[[5]]
[1] NA (22/45) (23/22)

as for k=2:

[[1]]
[1] NA

[[2]]
[1] NA

[[3]]
[1] NA NA (42/47) (41/37)

[[4]]
[1] NA NA (64/41) (54/39)

[[5]]
[1] NA NA (23/45)

I have little clue on how to approach this, I would think to perform some loops, but in R, it seems complicated. Please advice.

Upvotes: 1

Views: 1868

Answers (1)

akrun
akrun

Reputation: 887213

We loop through the list elements (lapply(..), if the length of the list element is 1, we return 'NA' or else divide the next value by the current value and concatenate with NA. We convert to numeric as the original list elements were character class.

 lapply(df$lengths, function(x) if(length(x)==1) NA
            else c(NA, as.numeric(x[-1])/as.numeric(x[-length(x)])))

Update

We could use the lag/lead function in dplyr/data.table for k values greater than 1.

library(dplyr)
k <- 2
lapply(df$lengths, function(x) {x <- as.numeric(x)
               if(length(x)==1) NA 
                 else c(rep(NA,k), na.omit(lead(x,k)))/na.omit(lag(x,k))})
#[[1]]
#[1] NA

#[[2]]
#[1] NA

#[[3]]
#[1]       NA       NA 0.893617 1.108108

#[[4]]
#[1]       NA       NA 1.560976 1.384615

#[[5]]
#[1]        NA        NA 0.5111111

Or without using any packages, we can do with head/tail functions

lapply(lst, function(x) {x <- as.numeric(x)
               if(length(x)==1) NA 
               else c(rep(NA, k), tail(x, -k)/head(x,-k))})

Upvotes: 1

Related Questions