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(ik) in each vector. Where a ratio cannot be obtained because element(ik) 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.
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)])))
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))})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.