Что не так с логикой c этой функции в R? - PullRequest
3 голосов
/ 28 марта 2020

Я пытаюсь построить функцию в R, которая вычисляет процентное изменение между строками на основе любого произвольного индекса, то есть между любой данной строкой и предыдущей или любой данной строкой и n предыдущими.

perc_change <- function(x,n) {
    y <- c()
    z <- c()
        for (i in 1:length(x)) {
        z[i] <- (x[i]/(x[i-n])-1)*100
    }
    y <- c(rep(NA,n),z[(n+1):length(z)])
    y
}

Когда n равен единице, функция работает правильно:

    x <- c(2,3.5,4,6)
    perc_change(x,1)

[1]       NA 75.00000 14.28571 50.00000

Но когда я изменяю на 2 или другое n, я получаю эту ошибку:

Error in z[i] <- (x[i]/(x[i - n]) - 1) * 100 : 
  replacement has length zero

Я просто не могу понять, почему и где лог c моей функции неверен, поэтому я ценю любой комментарий или предложение.

Ответы [ 2 ]

3 голосов
/ 28 марта 2020

В l oop, когда n больше 1, i, начинающийся с 1, может привести к отрицательному или нулевому индексу (то есть, когда n =2, 1 - 2). Чтобы избежать добавления условия if/else

perc_change <- function(x,n) {
      y <- c()
      z <- c()
          for (i in 1:length(x)) {
          if(i > n) {
          z[i] <- (x[i]/(x[i-n])-1)*100
         } else z[i] <- NA
     }
      y <- c(rep(NA,n),z[(n+1):length(z)])
      y
  }


perc_change(x,1)
#[1]       NA 75.00000 14.28571 50.00000
perc_change(x, 2)
#[1]        NA        NA 100.00000  71.42857
perc_change(x, 3)
#[1]  NA  NA  NA 200
2 голосов
/ 28 марта 2020

Следующая функция отстает от входного вектора, а затем вычисляет процентное изменение с помощью векторизованных операций, нет необходимости в циклах for. Функция lag - это копирование и вставка последних строк кода dplyr::lag.

perc_change <- function(x, n = 1) {
  lag <- function(x, n = 1){
    if(n == 0)
      return(x)
    xlen <- length(x)
    n <- pmin(n, xlen)
    out <- c(rep(NA, n), x[seq_len(xlen - n)])
    attributes(out) <- attributes(x)
    out
  }
  y <- lag(x, n)
  (x/y - 1)*100
}

x <- c(2, 3.5, 4, 6)
perc_change(x,1)
#[1]       NA 75.00000 14.28571 50.00000
perc_change(x, 2)
#[1]        NA        NA 100.00000  71.42857
...