R:Оптимизация/Предварительное выделение памяти — различия между версиями

Материал Psylab.info - энциклопедии психодиагностики
Перейти к: навигация, поиск
м (Артём Клевцов переименовал страницу R:Оптимизация/Циклы в R:Оптимизация/Предварительное выделение памяти без оставления перенаправ…)
м (Загрузка 2820-prealloc.wiki)
 
Строка 1: Строка 1:
 +
<!-- R:Оптимизация/Предварительное выделение памяти -->
 +
 +
 +
 
{{CC-BY-4.0|author=автором Артём Клевцов}}
 
{{CC-BY-4.0|author=автором Артём Клевцов}}
  
Строка 7: Строка 11:
 
Обратите внимание, что переменные, участвующие в цикле, должны быть объявлены до того, как будут использоваться.
 
Обратите внимание, что переменные, участвующие в цикле, должны быть объявлены до того, как будут использоваться.
  
{{r-code|code=<nowiki>> noaaloc <- function(n) {
+
{{r-code|code=<nowiki>noaaloc <- function(n) {
+     x <- NULL # объявляем пустую переменную
+
     x <- NULL # объявляем пустую переменную
+     for (i in seq_len(n))
+
     for (i in seq_len(n))
+         x[i] <- i * i
+
         x[i] <- i * i
+     x
+
     x
+ }
+
}
>
+
 
> alloc <- function(n) {
+
alloc <- function(n) {
+     x <- integer(n) # объявляем переменную нужного типа и размера
+
     x <- integer(n) # объявляем переменную нужного типа и размера
+     for (i in seq_len(n))
+
     for (i in seq_len(n))
+         x[i] <- i * i
+
         x[i] <- i * i
+     x
+
     x
+ }
+
}
> microbenchmark(noaaloc(10^4), alloc(10^4))
+
</nowiki>}}
Unit: milliseconds
+
 
           expr    min    lq median    uq   max neval
+
Теперь срвним время выполнения объявленных функций:
  noaaloc(10^4) 41.746 42.719 43.353 44.603 76.31   100
+
 
   alloc(10^4)  5.524 5.896 6.019 6.777 27.35   100</nowiki>}}
+
{{r-code|code=<nowiki>microbenchmark(noaaloc(10^4), alloc(10^4))
 +
#> Unit: milliseconds
 +
#>           expr    min    lq median    uq   max neval
 +
#> noaaloc(10^4) 38.545 39.596 39.977 40.595 78.476   100
 +
#>   alloc(10^4)  5.546 5.843 6.112 6.443  7.593   100
 +
</nowiki>}}
  
 
== Создание пустых объектов в R ==
 
== Создание пустых объектов в R ==
Строка 49: Строка 58:
 
Создание любого типа вектора можно также осуществить с помощью функции <code>vector()</code>. Данная функция принимает два аргумента: <code>mode</code>, указывающая тип данных и <code>length</code>, указывающая длину вектора. Например, создание вектора целых чисел, длиной 100 можно создать с помощью следующих команд:
 
Создание любого типа вектора можно также осуществить с помощью функции <code>vector()</code>. Данная функция принимает два аргумента: <code>mode</code>, указывающая тип данных и <code>length</code>, указывающая длину вектора. Например, создание вектора целых чисел, длиной 100 можно создать с помощью следующих команд:
  
{{r-code|code=<nowiki>> x <- integer(100)
+
{{r-code|code=<nowiki>x <- integer(100)
> x <- vector("integer", 100)</nowiki>}}
+
x <- vector("integer", 100)
 +
</nowiki>}}
  
 
=== Списки ===
 
=== Списки ===
Строка 56: Строка 66:
 
Списки можно создавать с помощью уже рассмотренной ранее функции <code>vector()</code>:
 
Списки можно создавать с помощью уже рассмотренной ранее функции <code>vector()</code>:
  
{{r-code|code=<nowiki>l <- vector("list", 10)</nowiki>}}
+
{{r-code|code=<nowiki>l <- vector("list", 10)
 +
</nowiki>}}
  
 
=== Матрицы ===
 
=== Матрицы ===
Строка 62: Строка 73:
 
Матрицы создаются с помощью соответствующей функции <code>matrix()</code>. Для создания матрицы необходимой размера, нам нужно указать количество строк и столбцов. Пример создания матрицы:
 
Матрицы создаются с помощью соответствующей функции <code>matrix()</code>. Для создания матрицы необходимой размера, нам нужно указать количество строк и столбцов. Пример создания матрицы:
  
{{r-code|code=<nowiki>> m <- matrix(NA, nrow = 100, ncol = 10)</nowiki>}}
+
{{r-code|code=<nowiki>m <- matrix(NA, nrow = 100, ncol = 10)
 +
</nowiki>}}
  
 
Поскольку матрица является также массивом, то матрицу можно также создать с помощью функции <code>array()</code>. Например:
 
Поскольку матрица является также массивом, то матрицу можно также создать с помощью функции <code>array()</code>. Например:
  
{{r-code|code=<nowiki>> m <- array(NA, dim = c(100, 10))</nowiki>}}
+
{{r-code|code=<nowiki>m <- array(NA, dim = c(100, 10))
 +
</nowiki>}}
  
 
Переменные, полученные с помощью функций <code>matrix()</code> и <code>array()</code> будут идентичными. Убедиться в этом можно с помощью функции <code>identical()</code>:
 
Переменные, полученные с помощью функций <code>matrix()</code> и <code>array()</code> будут идентичными. Убедиться в этом можно с помощью функции <code>identical()</code>:
  
{{r-code|code=<nowiki>> identical(matrix(NA, nrow = 100, ncol = 10),
+
{{r-code|code=<nowiki>identical(matrix(NA, nrow = 100, ncol = 10),
+           array(NA, dim = c(100, 10)))
+
           array(NA, dim = c(100, 10)))
[1] TRUE</nowiki>}}
+
#> [1] TRUE
 +
</nowiki>}}
  
 
Матрицы и массивы можно также получить путём преобразования векторов или списков. Для этого необходимо изменить атрибут объекта, в котом хранится информация о размерности объекта. Получиться информацию о размерности объекта можно с помощью функции <code>dim()</code>. Данная функция также позволяет изменять размерность объекта. Приведём примеры:
 
Матрицы и массивы можно также получить путём преобразования векторов или списков. Для этого необходимо изменить атрибут объекта, в котом хранится информация о размерности объекта. Получиться информацию о размерности объекта можно с помощью функции <code>dim()</code>. Данная функция также позволяет изменять размерность объекта. Приведём примеры:
  
{{r-code|code=<nowiki>> m <- array(NA, dim = c(3, 2)) # создаём двухмерный массив с 3 строками и 2 столбцами
+
{{r-code|code=<nowiki>m <- array(NA, dim = c(3, 2)) # создаём двухмерный массив с 3 строками и 2 столбцами
> m
+
m
     [,1] [,2]
+
#>     [,1] [,2]
[1,]  NA  NA
+
#> [1,]  NA  NA
[2,]  NA  NA
+
#> [2,]  NA  NA
[3,]  NA  NA
+
#> [3,]  NA  NA
> dim(m)
+
dim(m)
[1] 3 2
+
#> [1] 3 2
> dim(m) <- c(2, 3) # изменяем количество строк и столбцов
+
dim(m) <- c(2, 3) # изменяем количество строк и столбцов
> m
+
m
     [,1] [,2] [,3]
+
#>     [,1] [,2] [,3]
[1,]  NA  NA  NA
+
#> [1,]  NA  NA  NA
[2,]  NA  NA  NA
+
#> [2,]  NA  NA  NA
> dim(m)
+
dim(m)
[1] 2 3</nowiki>}}
+
#> [1] 2 3
 +
</nowiki>}}
  
 
Теперь мы может преобразовать вектор в матрицы путём присвоения вектору нужной нам размерности:
 
Теперь мы может преобразовать вектор в матрицы путём присвоения вектору нужной нам размерности:
  
 
{{r-code|code=<nowiki>m <- rep(NA, 1000)
 
{{r-code|code=<nowiki>m <- rep(NA, 1000)
dim(m) <- c(100, 10)</nowiki>}}
+
dim(m) <- c(100, 10)
 +
</nowiki>}}
  
 
Обратим внимание на то, что количество элементов в векторе и массиве должно быть одинаковым, в противном случае R выдаст ошибку. Результат данного преобразования будут также идентичен предыдущим примерам:
 
Обратим внимание на то, что количество элементов в векторе и массиве должно быть одинаковым, в противном случае R выдаст ошибку. Результат данного преобразования будут также идентичен предыдущим примерам:
  
{{r-code|code=<nowiki>> m1 <- matrix(NA, nrow = 100, ncol = 10)
+
{{r-code|code=<nowiki>m1 <- matrix(NA, nrow = 100, ncol = 10)
>
+
m2 <- rep(NA, 1000)
 
+
dim(m2) <- c(100, 10)
> m2 <- rep(NA, 1000)
+
identical(m1, m2)
> dim(m2) <- c(100, 10)
+
#> [1] TRUE
> identical(m1, m2)
+
</nowiki>}}
[1] TRUE</nowiki>}}
+
  
 
=== Таблицы данных ===
 
=== Таблицы данных ===
Строка 111: Строка 126:
 
Таблицы данных (<code>data.frame</code>) могут могу быть созданы путём объединения векторов, содержащих требуемые типы данных (см. [[{{FULLPAGENAME}}#Векторы| выше о создании векторов]]):
 
Таблицы данных (<code>data.frame</code>) могут могу быть созданы путём объединения векторов, содержащих требуемые типы данных (см. [[{{FULLPAGENAME}}#Векторы| выше о создании векторов]]):
  
{{r-code|code=<nowiki>> DF <- data.frame(A = integer(100),
+
{{r-code|code=<nowiki>d <- data.frame(A = integer(100),
                  B = character(100),
+
                B = character(100),
                  C = double(100),
+
                C = double(100),
                  D = double(100),
+
                D = double(100),
                  E = integer(100),
+
                E = integer(100),
                  stringsAsFactors = FALSE)</nowiki>}}
+
                stringsAsFactors = FALSE)
 +
</nowiki>}}
  
 
== Примечания ==
 
== Примечания ==

Текущая версия на 17:45, 28 мая 2014




Частой задачей, решаемой с помощью циклов, является выполнение расчётов и занесение результатов в переменную. Таким образом, результирующая переменная будет заполняться данными по мере работы цикла. Предварительное выделение памяти (preallocate) позволяет ускорить работу циклов, работающих с постепенной заполняемыми данными. Суть данного метода заключается в том, чтобы заранее выделить место в оперативной памяти, в которую будут записываться данные во время работы цикла. Выделение памяти осуществляется путём указания типа и размера переменной. Если этого не сделать, то при каждой новой итерации необходимо выделять новое место в памяти и производить туда запись.

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

КодR

<syntaxhighlight lang="r">noaaloc <- function(n) { x <- NULL # объявляем пустую переменную for (i in seq_len(n)) x[i] <- i * i x } alloc <- function(n) { x <- integer(n) # объявляем переменную нужного типа и размера for (i in seq_len(n)) x[i] <- i * i x } </syntaxhighlight>

Теперь срвним время выполнения объявленных функций:

КодR

<syntaxhighlight lang="r">microbenchmark(noaaloc(10^4), alloc(10^4)) #> Unit: milliseconds #> expr min lq median uq max neval #> noaaloc(10^4) 38.545 39.596 39.977 40.595 78.476 100 #> alloc(10^4) 5.546 5.843 6.112 6.443 7.593 100 </syntaxhighlight>

Создание пустых объектов в R

Векторы

integer(n) создаёт объект типа integer (число с фиксированной запятой) длинной n.
numeric(n) создаёт объект типа double (число с плавающей запятой) длинной n[1].
double(n) создаёт объект типа double (число с плавающей запятой) длинной n (число двойной точности).
single(n) создаёт объект типа double (число с плавающей запятой) длинной n (число одинарной точности).
complex(n) создаёт объект типа complex (комплексный тип данных) длинной n.
character(n) создаёт объект типа character (строковый тип данных) длинной n.
logical(n) создаёт объект типа logical (логический тип данных) длинной n.

Создание любого типа вектора можно также осуществить с помощью функции vector(). Данная функция принимает два аргумента: mode, указывающая тип данных и length, указывающая длину вектора. Например, создание вектора целых чисел, длиной 100 можно создать с помощью следующих команд:

КодR

<syntaxhighlight lang="r">x <- integer(100) x <- vector("integer", 100) </syntaxhighlight>

Списки

Списки можно создавать с помощью уже рассмотренной ранее функции vector():

КодR

<syntaxhighlight lang="r">l <- vector("list", 10) </syntaxhighlight>

Матрицы

Матрицы создаются с помощью соответствующей функции matrix(). Для создания матрицы необходимой размера, нам нужно указать количество строк и столбцов. Пример создания матрицы:

КодR

<syntaxhighlight lang="r">m <- matrix(NA, nrow = 100, ncol = 10) </syntaxhighlight>

Поскольку матрица является также массивом, то матрицу можно также создать с помощью функции array(). Например:

КодR

<syntaxhighlight lang="r">m <- array(NA, dim = c(100, 10)) </syntaxhighlight>

Переменные, полученные с помощью функций matrix() и array() будут идентичными. Убедиться в этом можно с помощью функции identical():

КодR

<syntaxhighlight lang="r">identical(matrix(NA, nrow = 100, ncol = 10), array(NA, dim = c(100, 10))) #> [1] TRUE </syntaxhighlight>

Матрицы и массивы можно также получить путём преобразования векторов или списков. Для этого необходимо изменить атрибут объекта, в котом хранится информация о размерности объекта. Получиться информацию о размерности объекта можно с помощью функции dim(). Данная функция также позволяет изменять размерность объекта. Приведём примеры:

КодR

<syntaxhighlight lang="r">m <- array(NA, dim = c(3, 2)) # создаём двухмерный массив с 3 строками и 2 столбцами m #> [,1] [,2] #> [1,] NA NA #> [2,] NA NA #> [3,] NA NA dim(m) #> [1] 3 2 dim(m) <- c(2, 3) # изменяем количество строк и столбцов m #> [,1] [,2] [,3] #> [1,] NA NA NA #> [2,] NA NA NA dim(m) #> [1] 2 3 </syntaxhighlight>

Теперь мы может преобразовать вектор в матрицы путём присвоения вектору нужной нам размерности:

КодR

<syntaxhighlight lang="r">m <- rep(NA, 1000) dim(m) <- c(100, 10) </syntaxhighlight>

Обратим внимание на то, что количество элементов в векторе и массиве должно быть одинаковым, в противном случае R выдаст ошибку. Результат данного преобразования будут также идентичен предыдущим примерам:

КодR

<syntaxhighlight lang="r">m1 <- matrix(NA, nrow = 100, ncol = 10) m2 <- rep(NA, 1000) dim(m2) <- c(100, 10) identical(m1, m2) #> [1] TRUE </syntaxhighlight>

Таблицы данных

Таблицы данных (data.frame) могут могу быть созданы путём объединения векторов, содержащих требуемые типы данных (см. выше о создании векторов):

КодR

<syntaxhighlight lang="r">d <- data.frame(A = integer(100), B = character(100), C = double(100), D = double(100), E = integer(100), stringsAsFactors = FALSE) </syntaxhighlight>

Примечания

  1. Эквивалент функции double()