Вопрос

Say I have a list:

> fs
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
[1] 61.90298 58.29699 54.90104 51.70293 48.69110

I want to "reverse fill" the rest of the list by using it's values. Example:

The [[3]] should have the function value of [[4]] pairs:

c( myFunction(fs[[4]][1], fs[[4]][2]), myFunction(fs[[4]][2], fs[[4]][3]), .... )

The [[2]] should have myFunction values of [[3]] etc...

I hope that's clear. What's the right way to do it? For loops? *applys? My last attempt, which leaves 1-3 empty:

n = length(fs)
for (i in rev(1:(n-1)))
  child_fs = fs[[i+1]]
  res = c()
  for (j in 1:(i+1))
    up = v(child_fs[j])
    do = v(child_fs[j+1])
    this_f = myFunction(up, do)
    res[j] = this_f
  fs[[i]] = res  
Это было полезно?

Решение

Make fs easily reproducible

fs <- list(NULL, NULL, NULL, c(61.90298, 58.29699, 54.90104, 51.70293, 48.69110))

To be able to show an example, make a trivial myFunction

myFunction <- function(a, b) {a + b}

You can loop over all but the last positions in fs (in reverse order), and compute each. Just call myFunciton with the vectors which are the next higher position's vectors without the last and without the first element.

for (i in rev(seq_along(fs))[-1]) {
  fs[[i]] <- myFunction(head(fs[[i+1]], -1), tail(fs[[i+1]], -1))
}

That assumes myFunction is vectorized (given vectors for inputs, will give a vector for output). If it isn't, you can easily make a version which is.

myFunction <- function(a, b) {a[[1]] + b[[1]]}

for (i in rev(seq_along(fs))[-1]) {
  fs[[i]] <- Vectorize(myFunction)(head(fs[[i+1]], -1), tail(fs[[i+1]], -1))
}

In either case, you get

> fs
[[1]]
[1] 453.2 426.8

[[2]]
[1] 233.398 219.802 206.998

[[3]]
[1] 120.200 113.198 106.604 100.394

[[4]]
[1] 61.90298 58.29699 54.90104 51.70293 48.69110

Другие советы

Really, what you have is a starting point

start <- c(61.90298, 58.29699, 54.90104, 51.70293, 48.69110)

a function you want to apply (I made this one up which adds 1 everywhere and deletes the last element)

myFunction <- function(x) head(x + 1, -1L)

and the number of times you want to apply the function (recursively):

n <- 3L

So I would write a function to apply the function n times recursively, then reverse the output list:

apply.n.times <- function(fun, n, x)
   if (n == 0L) list(x) else c(list(x), Recall(fun, n - 1L, fun(x)))

rev(apply.n.times(myFunction, n, start))

# [[1]]
# [1] 64.90298 61.29699
# 
# [[2]]
# [1] 63.90298 60.29699 56.90104
# 
# [[3]]
# [1] 62.90298 59.29699 55.90104 52.70293
# 
# [[4]]
# [1] 61.90298 58.29699 54.90104 51.70293 48.69110

Here is a one-line solution (if myFunction can be replaced with something like sum, or in this case rowSums):

Reduce( function(x,y) rowSums( embed(y,2) ), fs, right=TRUE, accumulate=TRUE )

If myFunction needs to accept 2 values and do something with them then this can be expanded a bit to:

Reduce( function(x,y) apply( embed(y,2), 1, function(z) myFunction(z[1],z[2]) ), 
    fs, right=TRUE, accumulate=TRUE )
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top