Добавление чисел c векторов неравной длины в список вместе со смещением на основе индекса? - PullRequest
2 голосов
/ 23 марта 2020

У меня есть список векторов, заданный следующим образом:

list_num <- list(c(1,1,1,1,1), c(2,2), c(5), c(3,3,3,3,3))

Я хочу добавить все эти векторы вместе, но сместить каждый вектор на значение его позиции в списке , т.е. при добавлении второго вектора c (2,2) мы добавляем его ко второй позиции и далее к первой. По сути, это выглядело бы следующим образом, где все элементы складываются вместе

list_num <- list(c(1,1,1,1,1), c(0,2,2), c(0,0,5), c(0,0,0,3,3,3,3,3))

# Output:
>> 1 3 8 4 4 3 3 3

Мой текущий подход заключается в создании вектора для размещения добавленных результатов и итерации по каждому элементу для добавления в него:

# Find the length for each of the vectors in the list
list_len <- unlist(lapply(list_num, function(x) { return(length(x))}))

# Find how long will the vector to add the results have to be
list_len <- 1:length(list_num)+list_len

# Generate a vector to house the added results
list_len <- rep(0, max(list_len)-1) 

# Then iterate over each of the elements by index i 
for(i in 1:length(list_num)){

  # Add the vector at position i to the subset of our aggregated vector
  list_len[i:(i+length(list_num[[i]])-1)] <- list_len[i:(i+length(list_num[[i]])-1)] + list_num[[i]]
}

print(list_len)
>> 1 3 8 4 4 3 3 3

Но я думаю, что это довольно неэффективно; Я ищу более эффективный способ агрегирования этих векторов go.

Ответы [ 3 ]

1 голос
/ 23 марта 2020

Мы можем использовать lapply, чтобы добавить смещение 0, используя rep

out <- lapply(seq_along(list_num), function(n) c(rep(0, n-1), list_num[[n]]))
out

#[[1]]
#[1] 1 1 1 1 1

#[[2]]
#[1] 0 2 2

#[[3]]
#[1] 0 0 5

#[[4]]
#[1] 0 0 0 3 3 3 3 3

Затем мы можем добавить NA, чтобы сделать длину равной и вычислить сумму по строке.

rowSums(sapply(out, `[`, 1:max(lengths(out))), na.rm = TRUE)
#[1] 1 3 8 4 4 3 3 3
0 голосов
/ 23 марта 2020

Решение Base R (двухступенчатое):

# Store a scalar valued at the length of longest vector in the list: 
vec_list_max_length <- max(lengths(vec_list))

# Set the length of each vector to be equal to the maximum length, rowbind the list
# together and get the sum of each row: 
rowSums(sapply(vec_list, function(x) {
  length(x) = vec_list_max_length
  return(replace(x, is.na(x), 0))
}))

Данные:

vec_list <- list(c(1,1,1,1,1), c(0,2,2), c(0,0,5), c(0,0,0,3,3,3,3,3))
0 голосов
/ 23 марта 2020

Требование не очень сложно кодировать на C ++, поэтому здесь есть опция, использующая Rcpp:

library(Rcpp)
cppFunction("NumericVector psumUnevenList(List a, int len) {
    NumericVector res(len), v;

    for (int i=0; i<a.length(); i++) {
        v = a[i];
        for (int j=0; j<v.length(); j++) {
            res[i+j] += v[j];
        }
    }

    return res;
}")
maxn <- max(seq_along(list_num) - 1L + lengths(list_num))
psumUnevenList(list_num, maxn)
#[1] 1 3 8 4 4 3 3 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...