Рекурсия и изменение глобальных объектов
23/02/14 13:37 Относится к категории: Анализ данных | R

Рекурсия и рекурсивные функции
Согласно википедии, "реку́рсия — наличие в определении, описании, изображении какого-либо объекта или процесса самого этого объекта или процесса, то есть ситуация, когда объект является частью самого себя. Термин «рекурсия» используется в различных специальных областях знаний — от лингвистики до логики, но наиболее широкое применение находит в математике и информатике".
Если говорить о функциональном программировании, то суть рекурсии сводится к вызову функции из тела (синтаксиса) этой же функции. Прежде, чем рассмотреть это на примере, надо поговорить о такой функции как scan(). Прежде всего она предназначена для считывания данных из текстовых файлов. Кроме этого, она может быть использована и для считывания данных введенных с клавиатуры. Выглядит это так:
Согласно википедии, "реку́рсия — наличие в определении, описании, изображении какого-либо объекта или процесса самого этого объекта или процесса, то есть ситуация, когда объект является частью самого себя. Термин «рекурсия» используется в различных специальных областях знаний — от лингвистики до логики, но наиболее широкое применение находит в математике и информатике".
Если говорить о функциональном программировании, то суть рекурсии сводится к вызову функции из тела (синтаксиса) этой же функции. Прежде, чем рассмотреть это на примере, надо поговорить о такой функции как scan(). Прежде всего она предназначена для считывания данных из текстовых файлов. Кроме этого, она может быть использована и для считывания данных введенных с клавиатуры. Выглядит это так:
1 2 3 4 5 6 | > temp <- scan("") # аргумент пустых кавычек используется для считывания данных с клавиатуры 1: 1 # ввод числового значения + Enter 2: 1 # ввод числового значения + Enter 3: 1 # ввод числового значения + Enter 4: # Enter для окончания ввода данных Read 3 items |
Как видно из первой строки, для ввода данных с клавиатуры необходимо использовать аргумент "". После этого сначала вводится числовое значение, а потом нажимается Enter. Далее этот процесс повторяется до тех пор пока Enter не будет нажат для пустого поля (т.е. без введения числового значения). В результате будет создан числовой вектор с соответствующим количеством элементов.
Как и любая другая функция, scan() имеет множество аргументов, которые вносят разнообразие в ее работу. В нашем случае будет интересен такой аргумент как nmax, ограничивающий величину вектора, в который вводятся данные.
Как и любая другая функция, scan() имеет множество аргументов, которые вносят разнообразие в ее работу. В нашем случае будет интересен такой аргумент как nmax, ограничивающий величину вектора, в который вводятся данные.
7 8 9 10 11 12 13 | > temp <- scan("", nmax=5) 1: 5 2: 4 3: 3 4: 2 5: 1 Read 5 items |
После введения пятого элемента ввод данных завершился автоматически. Наконец, можно вводить данные через пробел, а Enter нажать только в конце:
14 15 16 17 18 | > temp <- scan("", nmax=5) 1: 7 6 5 4 3 2 1 Read 5 items > i [1] 7 6 5 4 3 |
В 15 строке все данные вводятся через пробел и только потом нажимается Enter. При этом количество вводимых элементов равно 7, а не 5. Поэтому два последних значения не были записаны.
Теперь перейдем к рекурсивной функции:
Теперь перейдем к рекурсивной функции:
19 20 21 22 23 24 25 26 27 | > temporary10 <- function() { temp <- scan("",nmax=1) if (temp > 10) { print("ОШИБКА!!!") temporary10() } else { return(temp) } } |
В функции temporary10() с помощью 20 строки одно числовое значение записывается в скаляр temp. Далее это значение проверяется (строка синтаксиса 21): если оно больше 10, то была допущена ошибка ввода. Это продиктовано тем, что эта функция предназначена для ввода ответов на вопросы со шкалой от 0 до 10. При ошибке на экран выводится надпись "ОШИБКА!!!" (строка синтаксиса 22) и опять запускается функция temporary10(), то есть опять повторяется ввод данных (строка синтаксиса 23). Это будет происходить до тех пор, пока не будет введно значение в диапазоне от 0 до 10. После чего введенное значение будет передано далее (об этом ниже).
Изменение глобальных объектов
Одной из основ функционального программирования является невозможность изменения внешних по отношению к функции объектов с помощью ее синтаксиса (или изнутри тела функции). При этом они могут быть использованы внутри функций.
Такого рода внешние объекты часто называются глобальными, в то время как объекты созданные непосредственно внутри самой функции называются локальными. Примером локального объекта в функции temporary10() является скаляр temp. Как видно он создается внутри функции. Также он передается во внешнюю по отношению к функции среду.
Рассмотрим пример:
Одной из основ функционального программирования является невозможность изменения внешних по отношению к функции объектов с помощью ее синтаксиса (или изнутри тела функции). При этом они могут быть использованы внутри функций.
Такого рода внешние объекты часто называются глобальными, в то время как объекты созданные непосредственно внутри самой функции называются локальными. Примером локального объекта в функции temporary10() является скаляр temp. Как видно он создается внутри функции. Также он передается во внешнюю по отношению к функции среду.
Рассмотрим пример:
28 29 30 31 32 33 34 35 36 | > test <- 3 > fun <- function() { test <- test + 2 print(test) } > fun() [1] 5 > print(test) [1] 3 |
Сначала создается скаляр test. По отношению к функции fun() он является глобальным объектом. Внутри функции он используется для изменения своего собственного значения. Далее функция выводит новое значение для объекта test. Как видно, внутри функции финальное значение test равно 5 (что и выводится на экран в результате запуска функции). Но если после этого вывести значение test непосредственно, а не с помощью функции, то мы опять получим значение равное 3. Таким образом, реально значение test не изменилось.
Несмотря на это ключевое свойство функционального программирования, в каждом языке программирования есть свои способы изменения глобальных объектов из тела функции. В R это делается с помощью специального символа присваивания: <<- .
Модифицируем предыдущий пример:
Несмотря на это ключевое свойство функционального программирования, в каждом языке программирования есть свои способы изменения глобальных объектов из тела функции. В R это делается с помощью специального символа присваивания: <<- .
Модифицируем предыдущий пример:
37 38 39 40 41 42 43 44 45 | > test <- 3 > fun <- function() { test <<- test + 2 print(test) } > fun() [1] 5 > print(test) [1] 5 |
Как из него видно, скаляр модифицируется не только внутри функции, но и меняется за ее пределами. Таким же способом можно изменять и другие объекты (векторы, списки, фреймы данных).
А теперь вместе: ввод данных
Используя функцию temporary10(), а также подобные ей, и применив простой цикл с условными операторами можно создать базовый скрипт для ввода данных непосредственно на основании анкет.
Соответствующая функция выглядит следующим образом:
А теперь вместе: ввод данных
Используя функцию temporary10(), а также подобные ей, и применив простой цикл с условными операторами можно создать базовый скрипт для ввода данных непосредственно на основании анкет.
Соответствующая функция выглядит следующим образом:
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | > vvod <- function() { for (i in 1:9) { if (i==1) { var <- temporary10() print("Переменная (a1) введена успешно") anketa[[i]] <<- var } if (i==2) {...} if (i==3) {...} if (i==4) {...} if (i==5) {...} if (i==6) {...} if (i==7) {...} if (i==8) {...} if (i==9) { var <- temporary3() print("Переменная (c4) введена успешно") anketa[[i]] <<- var } } massiv <<- rbind(massiv,as.vector(anketa,mode="numeric")) print("АНКЕТА ВВЕДЕНА!!!") } |
Функция vvod() включает цикл из 9 итераций, каждая из которых связана с конкретным анкетным вопросом. Функция, используемая в каждой итерации, определяется количеством категорий вопроса. Таким образом, одни и те же функции будут использованы для разных вопросов с одинаковым количеством категорий. На каждом этапе введенные данные записываются в список anketa на соответствующую позицию (от 1 до 9, поскольку вопросов всего 9).
После завершения цикла полученный список преобразовывается в числовой вектор и записывается в заранее созданный фрейм данных massiv. Вот и все.
После завершения цикла полученный список преобразовывается в числовой вектор и записывается в заранее созданный фрейм данных massiv. Вот и все.
статью подготовил кандидат социологических наук Сергей Дембицкий
Data science (3)
Europe (2)
Geopolitics (2)
Infographics (1)
R (26)
Russia (2)
SPSS (2)
Ukraine (2)
Акционализм (1)
Анализ данных (27)
Аномия (1)
Выборка (1)
Выступления (3)
Геополитика (12)
Гражданское общество (2)
Демократизация (1)
Европа (4)
Интернет ресурсы (1)
Инфографика (8)
Исследовательские дизайны (1)
Историческая социология (10)
История социологии (5)
Киберспорт (1)
Книги (7)
Массивы (3)
Методология социальных исследований (1)
Методология социологических исследований (2)
Научная жизнь (3)
Новости (6)
Обратная связь (1)
Персоналии (3)
Православные конфессии в Украине (1)
Президентская власть (1)
Психологический дистресс (18)
Психология (5)
Публицистика (2)
Революция (1)
Результаты исследований (28)
Религия (3)
Россия (2)
Согласование концептов (4)
Социальная гетерогенность (1)
Социальная работа (1)
Социологическая теория (6)
Социологические тесты (1)
Социологическое образование (5)
Теория конфликта (2)
Теория социального измерения (8)
Украина (9)
Учебные планы (2)
Философия (1)
Шкалирование (36)
Экономика (1)
Эмпирическая социология (46)
Europe (2)
Geopolitics (2)
Infographics (1)
R (26)
Russia (2)
SPSS (2)
Ukraine (2)
Акционализм (1)
Анализ данных (27)
Аномия (1)
Выборка (1)
Выступления (3)
Геополитика (12)
Гражданское общество (2)
Демократизация (1)
Европа (4)
Интернет ресурсы (1)
Инфографика (8)
Исследовательские дизайны (1)
Историческая социология (10)
История социологии (5)
Киберспорт (1)
Книги (7)
Массивы (3)
Методология социальных исследований (1)
Методология социологических исследований (2)
Научная жизнь (3)
Новости (6)
Обратная связь (1)
Персоналии (3)
Православные конфессии в Украине (1)
Президентская власть (1)
Психологический дистресс (18)
Психология (5)
Публицистика (2)
Революция (1)
Результаты исследований (28)
Религия (3)
Россия (2)
Согласование концептов (4)
Социальная гетерогенность (1)
Социальная работа (1)
Социологическая теория (6)
Социологические тесты (1)
Социологическое образование (5)
Теория конфликта (2)
Теория социального измерения (8)
Украина (9)
Учебные планы (2)
Философия (1)
Шкалирование (36)
Экономика (1)
Эмпирическая социология (46)
January 2021
September 2020
March 2019
September 2018
August 2018
April 2018
March 2018
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013
October 2013
September 2013
December 2020
November 2020
October 2020September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
December 2019
November 2019
October 2019September 2019
August 2019
July 2019
June 2019May 2019
April 2019March 2019
February 2019
January 2019
December 2018
November 2018
October 2018September 2018
August 2018
July 2018
June 2018
May 2018April 2018
March 2018
February 2018
January 2018December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014November 2014
October 2014
September 2014August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013
October 2013
September 2013