вычислить сумму векторов с использованием R [duplicate]

Другой способ ответить на это, вместо того, чтобы увязнуть в тайных деталях точек последовательности и неопределенного поведения, - это просто спросить, , что они должны означать? Что было программистом пытаясь сделать?

Первый фрагмент, о котором спросили, i = i++ + ++i, в моей книге довольно сумасшедший. Никто никогда не напишет его в реальной программе, не очевидно, что он делает, нет никакого мыслимого алгоритма, который кто-то мог бы попытаться закодировать, что привело бы к этой конкретной надуманной последовательности операций. И поскольку для вас и меня не очевидно, что он должен делать, это прекрасно в моей книге, если компилятор не может понять, что он должен делать.

Второй фрагмент i = i++ , немного легче понять. Кто-то явно пытается увеличить i и присвоить результат i. Но есть несколько способов сделать это в C. Самый простой способ добавить 1 к i и присвоить результат обратно i, тот же почти для любого языка программирования:

i = i + 1

C , конечно, имеет удобный ярлык:

i++

Это означает, что «добавьте 1 к i и присвойте результат обратно i». Итак, если мы построим мешанину из двух, написав

i = i++

, то, что мы действительно говорим, это «добавить 1 к i» и присвоить результат обратно i, и присвоить результат обратно i ». Мы сбиты с толку, поэтому меня это слишком беспокоит, если компилятор тоже запутался.

Реально, единственный раз, когда эти сумасшедшие выражения получаются написанными, когда люди используют их как искусственные примеры того, как ++ должен работать. И, конечно же, важно понимать, как работает ++. Но одно практическое правило для использования ++: «Если не очевидно, что означает выражение, использующее ++, не пишите».

Мы проводили бесчисленные часы на comp.lang.c, обсуждая выражения, подобные этим, и , почему они не определены. Два моих более длинных ответа, которые пытаются объяснить, почему, заархивированы в Интернете:

12
задан user2834313 5 October 2013 в 19:56
поделиться

4 ответа

У вас есть вектор, а не массив. Вы можете использовать функцию rollapply из пакета zoo, чтобы получить то, что вам нужно.

> x <- c(1, 2, 3, 10, 20, 30)
> #library(zoo)
> rollapply(x, 3, sum)
[1]  6 15 33 60

Взгляните на ?rollapply для получения дополнительной информации о том, что делает rollapply и как его использовать.

22
ответ дан Jilber Urbina 23 August 2018 в 18:56
поделиться

Я собрал пакет для обработки этих видов функций rolling, которые предлагают функциональные возможности, подобные zoo 's rollapply, но с Rcpp на бэкэнд. Проверьте RcppRoll на CRAN.

library(microbenchmark)
library(zoo)
library(RcppRoll)

x <- rnorm(1E5)

all.equal( m1 <- rollapply(x, 3, sum), m2 <- roll_sum(x, 3) )

## from flodel
rsum.cumsum <- function(x, n = 3L) {
  tail(cumsum(x) - cumsum(c(rep(0, n), head(x, -n))), -n + 1)
}

microbenchmark(
  unit="ms",
  times=10,
  rollapply(x, 3, sum),
  roll_sum(x, 3),
  rsum.cumsum(x, 3)
)

дает мне

Unit: milliseconds
                 expr         min          lq      median         uq         max neval
 rollapply(x, 3, sum) 1056.646058 1068.867550 1076.550463 1113.71012 1131.230825    10
       roll_sum(x, 3)    0.405992    0.442928    0.457642    0.51770    0.574455    10
    rsum.cumsum(x, 3)    2.610119    2.821823    6.469593   11.33624   53.798711    10

Вам может показаться полезным, если скорость является проблемой.

19
ответ дан David Arenburg 23 August 2018 в 18:56
поделиться

Используя только базу R, которую вы могли бы сделать:

v <- c(1, 2, 3, 10, 20, 30)
grp <- 3

res <- sapply(1:(length(v)-grp+1),function(x){sum(v[x:(x+grp-1)])})

> res
[1]  6 15 33 60

Другой способ, более быстрый, чем sapply (сравнимый с @ flodel's rsum.cumsum), заключается в следующем:

res <- rowSums(outer(1:(length(v)-grp+1),1:grp,FUN=function(i,j){v[(j - 1) + i]}))
< hr>

Обновлен тест flodel:

x <- sample(1:1000)

rsum.rollapply <- function(x, n = 3L) rollapply(x, n, sum)
rsum.sapply    <- function(x, n = 3L) sapply(1:(length(x)-n+1),function(i){sum(x[i:(i+n-1)])})
rsum.filter <- function(x, n = 3L) filter(x, rep(1, n))[-c(1, length(x))]
rsum.cumsum <- function(x, n = 3L) tail(cumsum(x) - cumsum(c(rep(0, n), head(x, -n))), -n + 1)
rsum.outer <- function(x, n = 3L) rowSums(outer(1:(length(x)-n+1),1:n,FUN=function(i,j){x[(j - 1) + i]}))


library(microbenchmark)
microbenchmark(
  rsum.rollapply(x),
  rsum.sapply(x),
  rsum.filter(x),
  rsum.cumsum(x),
  rsum.outer(x)
)


# Unit: microseconds
#              expr      min        lq     median         uq       max neval
# rsum.rollapply(x) 9464.495 9929.4480 10223.2040 10752.7960 11808.779   100
#    rsum.sapply(x) 3013.394 3251.1510  3466.9875  4031.6195  7029.333   100
#    rsum.filter(x)  161.278  178.7185   229.7575   242.2375   359.676   100
#    rsum.cumsum(x)   65.280   70.0800    88.1600    95.1995   181.758   100
#     rsum.outer(x)   66.880   73.7600    82.8795    87.0400   131.519   100
9
ответ дан digEmAll 23 August 2018 в 18:56
поделиться

Если скорость вызывает беспокойство, вы можете использовать фильтр свертки и отрубать концы:

rsum.filter <- function(x, n = 3L) filter(x, rep(1, n))[-c(1, length(x))]

Или даже быстрее, напишите его как разницу между двумя суммарными суммами:

rsum.cumsum <- function(x, n = 3L) tail(cumsum(x) - cumsum(c(rep(0, n), head(x, -n))), -n + 1)

Оба используют только базовые функции. Некоторые тесты:

x <- sample(1:1000)

rsum.rollapply <- function(x, n = 3L) rollapply(x, n, sum)
rsum.sapply    <- function(x, n = 3L) sapply(1:(length(x)-n+1),function(i){
                                       sum(x[i:(i+n-1)])})

library(microbenchmark)
microbenchmark(
  rsum.rollapply(x),
  rsum.sapply(x),
  rsum.filter(x),
  rsum.cumsum(x)
)

# Unit: microseconds
#               expr       min        lq    median         uq       max neval
#  rsum.rollapply(x) 12891.315 13267.103 14635.002 17081.5860 28059.998   100
#     rsum.sapply(x)  4287.533  4433.180  4547.126  5148.0205 12967.866   100
#     rsum.filter(x)   170.165   208.661   269.648   290.2465   427.250   100
#     rsum.cumsum(x)    97.539   130.289   142.889   159.3055   449.237   100

Также я предполагаю, что все методы будут быстрее, если x и все применяемые веса были целыми числами, а не числами.

10
ответ дан flodel 23 August 2018 в 18:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: