Разница приводит к присвоению переменной внутри функции и вызову функции из функции в R - PullRequest
0 голосов
/ 10 января 2020

Я изо всех сил пытаюсь понять источник разницы в этих выходах для функции, которую я написал, которая удлиняет вектор до желаемой длины. В первом экземпляре функции я использовал присвоение переменной для current_length <- length(x):

lengthen_vector <- function(x, target_length){
  repeat{
    current_length <- length(x)
    x <- append(x, current_length + 1, after = current_length)
    current_length <- current_length + 1
      if(current_length == target_length) {
        return(x)
        break
      }
    }
  }

, что соответствует ожидаемой для целевой длины 20 от начальной длины 10:

[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Однако при переходе от назначения переменной к вызову функции length () во всей функции vector_lengthen (), как показано ниже:

lengthen_vector <- function(x, target_length){
  repeat{
    x <- append(x, length(x) + 1, after = length(x))
    length(x) <- length(x) + 1
      if(length(x) == target_length) {
        return(x)
        break
      }
    }
  }

... приводит к следующему:

[1] 1 2 3 4 5 6 7 8 9 10 11 NA 13 NA 15 NA 17 NA 19 NA

Какая разница между этими двумя причинами? Я не могу найти это.

1 Ответ

2 голосов
/ 10 января 2020

Значение length(x) <- n состоит в том, чтобы сделать длину x равной n, либо обрезав ее, либо расширив ее с помощью NA. Например,

x <- 1:3
length(x) <- 4
x
## [1]  1  2  3 NA

, так что если во второй версии x имеет 10 элементов, то после выполнения первого append x будет иметь 11 элементов, а затем length(x) <- length(x) + 1 расширит его до 12 элементов путем добавления NA.

Просто опустите оператор length(x) <- length(x) + 1, давая:

lengthen_vector1 <- function(x, target_length){
  repeat{
    x <- append(x, length(x) + 1, after = length(x))
      if(length(x) == target_length) {
        return(x)
        break
      }
    }
  }

Есть еще некоторые дополнительные улучшения, которые можно сделать:

  • удалить оператор break, поскольку он никогда не может быть достигнут, если он идет после оператора return. Поочередно переместите оператор return на после l oop.

  • , если target_length меньше или равно длине x, оно будет l oop навсегда. Это оставляет открытым то, что он должен делать в этом случае. Предположим, что если target_length меньше длины x, мы должны вернуть x без изменений. Для этого поместите оператор if перед оператором append и исправьте if, чтобы он возвращался, если target_length не превышает длину x. Кроме того, если это сделано, то if и repeat можно объединить в оператор while.

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

Таким образом, мы можем написать:

lengthen_vector2 <- function(x, target_length) {
  while(length(x) < target_length) {
    x <- c(x, length(x) + 1)
  }
  x
}

lengthen_vector2(1:10, 15)
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15

lengthen_vector2(1:10, 3)
## [1]  1  2  3  4  5  6  7  8  9 10

Также это можно сделать без циклов: конкатенация требуемой последовательности до конца x. Мы указываем, что последовательность заканчивается на target_length, а длина последовательности равна target_length - length(x) или 0, если она отрицательна.

lengthen_vector3 <- function(x, target_length) {
  c(x, seq(to = target_length, length = max(target_length - length(x), 0)))
}

Если мы хотим иметь возможность уменьшить длину, а также расширить ее, то вызовите length_vector3, используя head(x, target_length) вместо x.

lengthen_vector4 <- function(x, target_length) {
  lengthen_vector3(head(x, target_length), target_length)
}

lengthen_vector4(1:10, 15)
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15

lengthen_vector4(1:10, 3)
## [1]  1  2  3

или объедините последние два в одну функцию:

lengthen_vector5 <- function(x, target_length) {
  c(head(x, target_length), 
    seq(to = target_length, length = max(target_length - length(x), 0)))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...