Примеры программ на r

Недавно мы рассказали, для чего нужен и что умеет язык R. Теперь познакомимся с ним поближе и посмотрим, из чего он состоит и как на нём пишутся программы. На самом деле здесь 9 конструкций, но 10 звучит круче.

Точка с запятой в R не ставится.

Комментарии

Для комментариев в R используют решётку, как и в большинстве языков:

# это комментарий # его можно оставлять на той же строке, что и команда, а можно выносить в отдельную строку

Переменные и векторы

Чтобы объявить переменную, достаточно объявить её имя и присвоить ей что-нибудь, а R сам разберётся, какой тип тут нужен:

Если говорить совсем точно, то в R существует много структур данных: векторы, матрицы, списки, факторы и так далее. Самым важным считается вектор — это набор элементов, у которых одинаковый тип данных.

Сами типы векторов такие:

  • логический (logical),
  • целочисленный (integer),
  • вещественный (double),
  • комплексный (complex),
  • символьный (character),
  • двоичные данные (raw).

С векторами можно делать любые операции из векторной алгебры. Если что — у нас есть отличный цикл про векторы и матрицы. Матрицы в R тоже есть.

Лекция 1. Анализ данных на R в примерах и задачах

Внешние модули

Сила языка R — во внешних модулях или пакетах, которые существенно расширяют возможности базового набора команд. Они позволяют быстрее строить нейросети, вторые — анализировать данные, а третьи заточены на работу со статистикой.

Чтобы подключить внешний модуль, используют команду library():

library(pipelearner) # подключаем модуль для разбиения данных на блоки, чтобы лучше обучать модель

Ввод и вывод

Для вывода значения переменной достаточно просто написать её имя:

x # выведет значение x y # выведет значение y

А для вывода сообщения нужна команда print(): print(«Привет, это журнал Код!»).

Если нужно вывести график функции, можно использовать стандартную команду plot() — она построит график в виде точек, гистограмм или соединит всё линиями.

plot(x,y) # в x и y — наборы значений

Так как R предназначен для работы с большими объёмами данных, то ввод данных идёт не с клавиатуры, а из файлов:

Но если нужен ввод с клавиатуры, используйте команду readline():

input

Присваивание и сравнение

Сравнение обозначается как обычно, двойным знаком равно:

a == 1331

А вот присваивания есть два, стрелка и знак равенства.

x = 15 y

Если не вдаваться в нюансы использования, то стрелка отвечает за глобальное использование переменной, чтобы она была видна всем, а знак равенства — за локальное использование, то есть внутри какой-то подпрограммы.

Условный оператор if

В нём никаких сюрпризов: фигурные скобки, как в JavaScript, и скобки для выражения, которое проверяем:

if(x >= 100 x < 1000)< y = 12 print(y) >else

Цикл for

А вот цикл for похож уже на Python с его диапазоном для организации шага цикла. Остальное всё то же самое — фигурные скобки тоже нужны для группировки нескольких команд:

R для каждого, Урок 1


for(i in 1:100)

Функции

Работают и объявляются точно так же, как и в других языках высокого уровня. Единственное отличие в том, что функция объявляется не сама по себе, а как бы отправляется в переменную (как стрелочная функция в JavaScript):

run.10km print(y) > run.10km(0.1)

Классы, методы и объекты

R — полностью объектно-ориентированный язык. Каждый элемент в нём — это объект, даже функции и таблицы. Поэтому всё, что работает в ООП (классы, методы и объекты), работает и в R, но на более сложном уровне абстракции.

В R можно посмотреть список всех доступных методов для любого объекта с помощью команды methods(). Например, если нам нужно понять, какие методы есть у команды plot(), которая рисует нам график, то нам нужно написать в консоли среды разработки: methods(plot)

В ответ мы получим все доступные методы:

[1] plot.acf* plot.data.frame* plot.decomposed.ts* [4] plot.default plot.dendrogram* plot.density* [7] plot.ecdf plot.factor* plot.formula* [10] plot.function plot.hclust* plot.histogram* [13] plot.HoltWinters* plot.isoreg* plot.lm* [16] plot.medpolish* plot.mlm* plot.ppr* [19] plot.prcomp* plot.princomp* plot.profile.nls* [22] plot.raster* plot.spec* plot.stepfun [25] plot.stl* plot.table* plot.ts [28] plot.tskernel* plot.TukeyHSD*

Кстати, метод default срабатывает, когда plot() получает на обработку объект неизвестного ей класса.

Источник: thecode.media

Учимся программировать в R: логические операторы, if else, for и while

Создание скриптов и функций в R зачастую требует навыки программирования, а именно: использования логических операторов (например, >= «больше или равно») и управляющих структур (if else, for и while). Благодаря им мы можем задавать условия, при которых будет выполняться то или иное действие, а также определять порядок выполнения действий и их повторяемость.

Другими словами, управляющие структуры автоматизируют процессы анализа данных, прописав возможные сценарии и условия их выполнения. Программирование на языке R позволяет не только уменьшить код скрипта/функции, но и существенно сэкономить время, доверив всю рутинную работу компьютеру.

Логические операторы в R

Операторы в R можно разделить на две категории: арифметические и логические. Арифметическими операторами являются знакомые нам со школы знаки сложения, вычитания, умножения и деления, а также знак возведения в степень и модульные операции (+, -, *, /, ^, %% и %/%, соответственно). Логические операторы обычно используются при проверке условий и выдают значения: TRUE или FALSE.

В языке R существует 9 логических операторов, без знания которых программирование не представляется возможным.

Оператор Описание
> Больше
>= Больше или равно
Меньше
Меньше или равно
== Равно
!= Не равно
=» и «= wp-block-preformatted»># Верно ли утверждение, что 11 в третьей степени не равняется 1111? 11^3 != 1111 [1] TRUE # 11 в третьей степени меньше 1111? 11^3 < 1111 [1] FALSE # То есть 11 в третьей степени это 11*11*11 # и оба этих выражения равняются 1331? a = 11^3 b = 11*11*11 a значение/переменная 1″, на правой — «значение/переменная 2», в то время, как сам оператор является критерием, по которому R «судит» о правильности утверждения. Если утверждение верно, то в командной строке будет выведено TRUE, если утверждение ложно — FALSE. Следует добавить, что логические операторы работают со всеми типами данных: от векторов до таблиц, что делает их незаменимым инструментом в стат. анализе.

a = 5 [1] FALSE FALSE FALSE TRUE TRUE TRUE b = 5] b [1] 5 8 10

Теперь мы знаем, что такое логические операторы и готовы к изучению второй части этой статьи — работе с управляющими структурами в R.

Программирование и управляющие структуры

Существует около десятка управляющих структур на которых базируется программирование в R. Среди них можно выделить три наиболее используемые: оператор условий if else и два типа циклов — for и while.

Оператор условий if else используется, когда есть два и более варианта развития сценария: если условие выполняется — «делай это», если не выполняется — «делай то». Суть же циклов в том, что они повторяют одно и то же действие несколько раз: в цикле while действие повторяется пока не выполнится условие цикла, а в цикле for — определенное пользователем количество раз.

Циклы while и for в R

На рисунке изображены три вида управляющих структур, где стрелки отображают поток данных. Если условие выполняется (TRUE), то поток данных движется вниз от условия, если нет (FALSE), то вправо и вниз. Как можно заметить в структурах типа while и for при выполнении условия, поток данных циркулирует по кругу: именно по этой причине их и называют циклами. Давайте разберем каждую из этих структур на практике!

Оператор условий if else в R

В языке программирования R оператор условий if else состоит из трех элементов:

  1. индикатор структуры: if, else или else if (в случае, когда условий больше одного)
  2. условие структуры, заключенного в круглые скобки (где находится условие для выполнения действия).
  3. тело структуры, заключенного в фигурные скобки (где находится код самого действия)

Пример 1: покупай больше, плати меньше — if без else

Давайте создадим простейший вариант структуры if else, когда есть только одно условие при соблюдении которого, требуется выполнить дополнительное действие в сценарии. Допустим, в магазине акция: при покупке на сумму от 100$, предоставляется 12.5% скидка. Сколько мы в итоге потратим если наша покупка ( x ) была на сумму 120$?

x = 120 if(x >= 100) x = x — x*12.5/100 print(x) > [1] 105

Итак, в скобках находится условие, что общая стоимость покупок будет меняться только в случае, если x >= 100 . Внутри фигурных скобок отображен код, иллюстрирующий механизм изменения финальной стоимости. Как Вы видите, индикатор else был не указан в конструкции. Мы его опустили, так как в случае, если x < 100 , то никаких действий производиться не будет.

Следует также отметить, что для того, чтобы изменить показатель x , и проверить финальную цену, нам придется запускать весь код конструкции заново. Это непрактично, именно поэтому конструкцию if else чаще всего используют внутри функции. Давайте создадим и запустим функцию с оператором условий if else внутри.

shop if(x >= 100) x = x — x*12.5/100 print(x) > > shop(120) [1] 105 shop(50) [1] 50

Пример 2: прогрессивная система скидок — индикатор else if

Добавим второе условие: если сумма покупок больше или равна 1000$, то магазин предоставит 25% скидку. Для этого условия мы будем использовать индикатор else if. В этом случае, нужно также изменить параметры первого условия, где x должно быть больше или равно 100, но меньше 1000. Если же ни первое, ни второе условие не соблюдается, то выведем на экран сообщение «No discounts» после финальной цены при помощи индикатора else.

shop if(x >= 100 x < 1000) x = x — x*12.5/100 print(x) > else if(x >= 1000) x = x — x*20/100 print(x) > else print(c(x, «No discounts»)) > > shop(20) [1] 20 «No discounts» shop(200) [1] 175 shop(2000) [1] 1600

Также внутрь оператора условий if else можно вставить другой оператор if else, либо циклы while или for. Подобное свойство вложения управляющих структур позволяет реализовывать сложные многоуровневые сценарии (алгоритмы) на практике, создавая функции с несколькими аргументами, и множеством условий и циклов внутри.

Циклы while и for в R

Ранее мы упоминали, что при неоднократном повторении кода в скрипте следует использовать R функции, чтобы уменьшить размер кода и сделать его более читабельным. Однако, в большинстве ситуаций это будет сделать невозможно без использования циклов внутри функции. Если есть условие, при исполнении которого потребуется повторить действие, используйте цикл while (перевод с англ.: «до тех пор, пока»). Если условия нет, но надо выполнить действие определенное количество раз, воспользуйтесь циклом for.

Пример 3: уникальная методика бега — цикл for

Допустим у нас есть друг который решил заняться бегом. До этого он не бегал и находится в ужасной физической форме: максимум сколько он смог пробежать за первую тренировку — 100 метров. Друг пообещал, что через 100 дней он за тренировку будет пробегать больше 10 км, так как он разработал собственную методику: он будет заниматься ежедневно и прибавлять по 5% к дистанции от предыдущей нагрузки.

Проверим при помощи цикла for сработает ли его методика в теории. Для этого создадим функцию run.10km и переменную y , обозначающую дистанцию тренировки (в км). Внутри круглых скобок цикла for напишем что круг будет повторяться 100 раз, а внутри квадратных код вычислений дистанции для каждого дня. Дистанция последнего дня будет выделена на экран при использовании функции.

run.10km for(i in 1:100) y > print(y) > run.10km(0.1) [1] 13.15013

Оказалось, Ваш друг действительно прав: благодаря этой методике он сможет пробежать через 100 дней более 13 км за тренировку! Теоретически.

Пример 4: может тренироваться реже, но интенсивнее — цикл while

Однако, тренироваться ежедневно без выходных для начинающего — это неминуемый путь к физическому и психическому истощению. Чтобы у друга дни нагрузок чередовались с днями отдыха, давайте предложим ему альтернативную методику: тренироваться через день, но прибавляя к дистанции по 10% от предыдущей нагрузки (вместо 5%).

Рассчитаем, используя цикл while, через сколько дней друг начнет пробегать более 10 км за тренировку и выведем результат в виде таблицы каждая строчка которой отображает день тренировки и предполагаемую дистанцию.

alter.10km i Day Distance while(y i y Day Distance > DF return(DF) > results tail(results, 3) Day Distance 48 95 8.819749 49 97 9.701723 50 99 10.671896

Таким образом, наш друг с 99-го дня станет пробегать более 10 км за тренировку занимаясь реже, но интенсивнее! Выглядит, как более реалистичный вариант, но что скажет друг?

Заключение

Сегодня мы использовали простые и наглядные примеры, чтобы понять принцип и суть программирования на языке R. Знания логических операторов и структур управления позволят Вам реализовывать любые идеи в статистическом анализе, не ограничиваясь существующими решениями в R пакетах и интернете. Программирование на R не только экономит Ваше время, но и делает статистический анализ увлекательным и творческим занятием. Дерзайте!

Комментарии: 17

Сентябрь 19, 2022 в 05:29 Уведомляем,Baм пpиcлaли лoтepeйный билeт. Пepeйдитe пo ccылкe дaлee ->> https://forms.yandex.com/cloud/63147fd81a862292755fbcc5/?hs=7158ed5412051f8736495dcc532eacc4! = China» . Ваш код должен выглядеть примерно так: new.df Вот ресурс, на котором кратко описано как отбирать данные (я на этом сайте не писал об этом еще), раздел Selecting Observations:
https://www.statmethods.net/management/subset.html

Октябрь 13, 2020 в 10:35 Кирилл

Спасибо! Через ваш код не получилось выбрать наблюдение, но получилось с помощью функции «subset». Подскажите, а как посмотреть среднее число заболевших по всем странам? Через функцию «mean» можно посмотреть только среднее число заболевших по всем странам.

Октябрь 13, 2020 в 11:31 Samoedd (Автор записи)
https://samoedd.com

Для этого надо использовать функцию aggregate .
aggregate(df[, «Название колонки с наблюдениями»], list(df$Country), mean) Если в таблицу хотите вывести, то просто присвойте имя (например mean.df ):
mean.df

Апрель 29, 2020 в 19:53 Евгений

Спасибо за статью! В примере с else if вы сказали что x должно быть больше или равно 100, но меньше 1000. А в коде нет такого. Второе условие else if у меня не срабатывает.

Май 2, 2020 в 20:18 Samoedd (Автор записи)
https://samoedd.com

Здравствуйте, Евгений! Спасибо за замечание, исправил:
Пример 2.
Было: if(x >= 100)
Стало: if(x >= 100 x ↓

Март 27, 2020 в 06:05 Таня

Добрый день! А вы ещё работаете в среде R ? Извините за вопрос (возможно наглость) смогли бы вы помочь мне с двумя практическими работами. Благодаря вашим темам 3 штуки я сделала. Спасибо заранее

Март 27, 2020 в 11:17 Samoedd (Автор записи)
https://samoedd.com
Июль 1, 2018 в 15:05 Анастасия

Пожскажите, пожалуйста, почему в задаче про бег (for) в конце в скобке стоит 0.1
run.10km(0.1)
[1] 13.15013 Спасибо!)

Июль 2, 2018 в 10:30 Samoedd (Автор записи)
https://samoedd.com

Здравствуйте, Анастасия! «Для этого создадим функцию run.10km и переменную y, обозначающую дистанцию тренировки (в км).» Т.к. друг начинал со 100 метров, а по условию мы договорились, что работаем с километрами, то вводим 0.1 км вместо 100 метров. Но можно ввести и 100 метров, просто программа тогда выдаст ответ тоже в метрах: на сотый день наш друг пробежит 13150.13 метров;-)

Источник: samoedd.com

Введение в R. Разбираемся в анализе данных с использованием статистического пакета

В прош­лой статье из декабрь­ско­го номера я начал говорить об ана­лизе дан­ных и закон­чил на том, как быс­тро решить задачу линей­ной рег­рессии на R. Сегод­ня я более под­робно рас­ска­жу об R как о язы­ке прог­рамми­рова­ния.

Ког­да‑то это был язык для работы со ста­тис­тикой, но сей­час его впол­не мож­но счи­тать язы­ком обще­го наз­начения (хотя основную свою нап­равлен­ность он сох­ранил). Кто не верит, может заг­лянуть на стра­нич­ку про­екта Shiny, с помощью которо­го любой может соз­давать пол­ноцен­ные веб‑при­ложе­ния на R.

Ну да лад­но, нас язык R инте­ресу­ет имен­но в той области, где он дей­стви­тель­но хорош. В этой статье я рас­ска­жу о самых базовых объ­ектах в язы­ке и его осо­бен­ностях. Кто‑то муд­рый дав­но заметил, что самое хорошее в язы­ке R — это то, что он был соз­дан спе­циалис­тами по ста­тис­тике, а самое пло­хое — то, что он был соз­дан спе­циалис­тами по ста­тис­тике :).

Опус­тив воп­росы уста­нов­ки R, с которы­ми доволь­но лег­ко спра­вить­ся (тем более что про это я нем­ного уже писал в прош­лой статье), прис­тупим к изу­чению язы­ка.

Все, что вы хотели знать о функции, но боялись спросить

В язы­ке R дос­тупна очень боль­шая инфраструк­тура пакетов и, как следс­твие, совер­шенно неверо­ятное количес­тво фун­кций для пов­седнев­ного исполь­зования. Что делать, если ты зна­ешь наз­вание, но не пом­нишь пра­виль­ное упот­ребле­ние фун­кции? Решени­ем ста­нет очень при­лич­ный help, пра­виль­ным обра­зом встро­енный в сис­тему. Для того что­бы получить справ­ку об исполь­зовании той или иной фун­кции, дос­таточ­но наб­рать ?имя_функции .

Векторы

Нач­нем с базовых объ­ектов, из которых сос­тоит язык. В боль­шинс­тве язы­ков прог­рамми­рова­ния, с которы­ми тебе при­ходи­лось иметь дело, при­митив­ными объ­екта­ми явля­ются чис­ла, объ­екты булева типа и про­чие дей­стви­тель­но при­митив­ные вещи.

В язы­ке R пол­но сюр­при­зов, и пер­вый из них зак­люча­ется в том, что при­митив­ным объ­ектом в R явля­ется век­тор, то есть совокуп­ность зна­чений одной при­роды. К при­меру, век­тор вещес­твен­ных чисел. Хочет­ся спро­сить, а как быть с обыч­ными чис­лами? Ска­жем, с чис­лом 10. Ответ на этот воп­рос доволь­но прост — это век­тор из одно­го эле­мен­та.

Век­торы быва­ют сле­дующих типов:

  • це­лые;
  • чис­ловые (вещес­твен­ные);
  • сим­воль­ные;
  • ком­плексные;
  • ло­гичес­кие.

По умол­чанию чис­ла в R — это вещес­твен­ные чис­ла, то есть чис­ла с пла­вающей запятой. Для того что­бы явно ука­зать R, что чис­ло, с которым ты собира­ешь­ся иметь дела, целое, нуж­но добавить суф­фикс L. Нап­ример, 10L. Это лег­ко иллюс­три­рует сле­дующий код:

[ 1 ] «integer»

Здесь будет исполь­зовать­ся сим­вол приг­лашения > , что­бы отли­чать код от отве­та сис­темы. В работе с чис­лами сущес­тву­ет спе­циаль­ный сим­вол Inf для пред­став­ления бес­конеч­ности.

Сле­дует обра­тить вни­мание на опе­ратор прис­ваива­ния < — . Рас­смот­рим сле­дующий фраг­мент:

> x # печатаем x
> print ( x ) # еще раз печатаем

В этом, казалось бы, оче­вид­ном фраг­менте кода есть два важ­ных момен­та: печатать мож­но, прос­то ука­зывая имя перемен­ной в стро­ке или исполь­зуя фун­кцию, пред­назна­чен­ную для печати. Это доволь­но харак­терно для всех язы­ков, в которых есть инте­рак­тивный интер­пре­татор REPL (Read — Evaluate — Print Loop). Фун­кция print ско­рее исполь­зует­ся для печати внут­ри дру­гих фун­кций для отладки или прос­то для вывода какой‑либо информа­ции. Что более важ­но и менее оче­вид­но, стро­ка [ 1] 10 , выводи­мая в качес­тве резуль­тата в R, говорит, что это пер­вый (и единс­твен­ный) эле­мент век­тора.

Чис­ло 1 в квад­ратных скоб­ках выводит­ся для удобс­тва чте­ния. К при­меру, если век­тор не вле­зает в ширину экра­на, то он раз­бива­ется на стро­ки и чис­ла перед каж­дой стро­кой — это индекс эле­мен­та век­тора, с которо­го начина­ется дан­ная стро­ка.

Для соз­дания обыч­ного век­тора исполь­зует­ся фун­кция c :

> x < — c ( 1 , 2 , 3 )

Так же как и во мно­гих дру­гих язы­ках, мож­но соз­давать век­торы, ука­зывая интервал зна­чений:

> x < — c ( 1 : 3 )

Ка­залось бы, резуль­тат тот же, одна­ко все не сов­сем так. Так как это целочис­ленный интервал, содер­жимое вто­рого век­тора — это целые чис­ла, а пер­вого — вещес­твен­ные. Что лег­ко про­верить с помощью фун­кции typeof . В пос­леднем слу­чае еще мож­но писать прос­то x < — 1: 3 . Зна­чения булева типа в язы­ке R выг­лядят как TRUE и FALSE или прос­то T и F . Для того что­бы соз­дать пус­той век­тор нуж­ного типа, необ­ходимо исполь­зовать фун­кцию vector .

> x < — vector ( «numeric» , length = 10 )
[ 1 ] 0 0 0 0 0 0 0 0 0 0

Не­явное пре­обра­зова­ние типов в R хорошо иллюс­три­рует­ся сле­дующим при­мером:

> x < — c ( «a» , TRUE , 1. 3 )
[ 1 ] «a» «TRUE» «1. 3»
> y < — c ( 2 , TRUE , FALSE )

Час­то быва­ет необ­ходимо вос­поль­зовать­ся явным пре­обра­зова­нием типов. Рас­смот­рим при­мер:

> as ( TRUE , «character» )
> as. character ( TRUE )

Два строч­ки дела­ют в точ­ности то же самое, одна­ко с точ­ки зре­ния чита­емос­ти кода
вто­рой под­ход выг­лядит более пред­почти­тель­ным. Вооб­ще, фун­кции соз­дания, про­вер­ки и пре­обра­зова­ния типов лег­ко запом­нить сле­дующим обра­зом. Для соз­дания (пус­того век­тора строк) исполь­зует­ся character( length=5) , где length — количес­тво эле­мен­тов, is. character исполь­зует­ся для срав­нения, а as. character для пре­обра­зова­ния. Ког­да пре­обра­зова­ние невоз­можно, то его резуль­татом будет спе­циаль­ное зна­чение NA .

Эле­мен­ты век­тора могут быть заиме­нова­ны, это мож­но сде­лать сле­дующим обра­зом:

> v < — c ( x = 1. 0 , y = 2. 5 , z = -0. 1 )
1. 0 2. 5 -0. 1
> u < — c ( 1. 0 , -0. 5 , -0. 5 )
> names ( u ) < — c ( «x» , «y» , «z» )

Матрицы

С век­торами все доволь­но прос­то, давай теперь поп­робу­ем разоб­рать­ся с дру­гой полез­ной струк­турой дан­ных — мат­рицами. Для соз­дания мат­рицы есть спе­циаль­ная фун­кция matrix :

> m < — matrix ( nrow = 2 , ncol = 3 )
[ , 1 ] [ , 2 ] [ , 3 ]
[ 1 , ] NA NA NA
[ 2 , ] NA NA NA

Как вид­но, изна­чаль­но соз­дает­ся пус­тая мат­рица. Для того что­бы получить раз­меры мат­рицы, сущес­тву­ет спе­циаль­ный атри­бут dim :

> attributes ( m )

Сле­дует отме­тить, что в смыс­ле хра­нения дву­мер­ных объ­ектов (мас­сивов, мат­риц) все язы­ки делят­ся на две груп­пы: те, что хра­нят мат­рицы по стро­кам, такие как C и Java, и те, что хра­нят по стол­бцам, — это, к при­меру, FORTRAN и R. В том, что это имен­но так, лег­ко убе­дить­ся сле­дующим обра­зом:

> m < — matrix ( 1 : 6 , nrow = 2 , ncol = 3 )
[ , 1 ] [ , 2 ] [ , 3 ]

При­чем задавать дву­мер­ную струк­туру мож­но, прос­то добав­ляя атри­бут dim к век­тору:

> dim ( v ) < — c ( 2 , 3 )
[ , 1 ] [ , 2 ] [ , 3 ]

Сверх того, стро­кам и колон­кам мат­рицы мож­но давать име­на:

> m < — matrix ( 1 : 4 , nrow = 2 , ncol = 2 )
> dimnames ( m ) < — list ( c ( «a» , «b» ) , c ( «c» , «d» ) )

В язы­ке R сущес­тву­ет так­же механизм соз­дания дву­мер­ных струк­тур из одно­мер­ных с помощью опе­раций при­соеди­нения стро­ки или стол­бца:

> y < — 11 : 13
> cbind ( x , y )
> rbind ( x , y )
[ , 1 ] [ , 2 ] [ , 3 ]
y 11 12 13

О том, как работать с отдель­ными эле­мен­тами струк­тур дан­ных, я напишу чуть поз­же, а пока про­дол­жим раз­бирать­ся с самими струк­турами.

Списки и факторы

В этом раз­деле рас­смот­рим еще две полез­ные струк­туры дан­ных. Пер­вая — это, конеч­но, спи­сок. Дело в том, что час­то при­ходит­ся хра­нить дан­ные раз­ного типа в одном мес­те.

Как мы зна­ем, век­тор здесь не под­ходит, потому что его эле­мен­ты дол­жны быть одно­го типа, поэто­му в R пре­дус­мотре­ны спис­ки:

> lst < — list ( «hello» , 1. 5 , TRUE , 1+2i )

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

> l < — list ( a = «test» , b = 3. 14 )

Во мно­гих язы­ках прог­рамми­рова­ния есть перечис­лимый тип дан­ных. Он нужен для того, что­бы работать с дан­ными, в качес­тве зна­чения которых могут выс­тупать эле­мен­ты конеч­ного мно­жес­тва. Ког­да такого типа в язы­ке нет, этот воп­рос реша­ется с помощью кон­стант для соот­ветс­тву­юще­го набора зна­чений. В язы­ке R для обес­печения подоб­ной фун­кци­ональ­нос­ти есть спе­циаль­ный тип — фак­тор:

> x < — factor ( c ( «yes» , «no» , «yes» , «no» , «no» ) )
[ 1 ] yes no yes no no
Levels : no yes

Здесь соз­дает­ся век­тор фак­торов с дву­мя воз­можны­ми зна­чени­ями: yes и no. Мож­но, к при­меру, под­счи­тать, сколь­ко соот­ветс­тву­ющих зна­чений есть в нашем век­торе:

Фрейм данных (Data Frame)

Фрейм дан­ных — один из самых полез­ных типов дан­ных в R. Ког­да мы работа­ем с реаль­ными таб­личны­ми дан­ными, имен­но этот тип пред­став­ляет таб­лицы. В отли­чие от мат­риц, дан­ный тип поз­воля­ет хра­нить раз­личные типы дан­ных в раз­ных колон­ках. С точ­ки зре­ния хра­нения этот тип дан­ных мож­но пред­ста­вить как спи­сок спе­циаль­ного вида, где эле­мен­тами спис­ка явля­ются спис­ки оди­нако­вой дли­ны (колон­ки). Для заг­рузки фрей­ма дан­ных из CSV-фай­ла сущес­тву­ет фун­кция read. csv , которая уже встре­чалась нам в пре­дыду­щей статье этой серии.

Мож­но соз­дать фрейм дан­ных вруч­ную, нап­ример так:

> x < — data. frame ( a = c ( F , F , T , T ) , b = c ( F , T , F , T ) , or = c ( F , T , T , T ) )
1 FALSE FALSE FALSE
2 FALSE TRUE TRUE
3 TRUE FALSE TRUE
4 TRUE TRUE TRUE

По­мимо атри­бута names , для фрей­ма дан­ных так­же есть row. names :

> row. names ( x )
[ 1 ] «1» «2» «3» «4»

Доступ к элементам

Как ты мог заметить, до сих пор я рас­ска­зывал лишь о том, какие быва­ют струк­туры дан­ных, но ничего не ска­зал про то, как получать дос­туп к отдель­ным эле­мен­там или под­мно­жес­твам. Пос­мотрим, как это работа­ет, на прос­том при­мере с век­тором:

> x < — c ( 11 , 21 , 31 , 41 , 11 , 21 , 31 )
[ 1 ] 31 41 31
[ 1 ] FALSE FALSE TRUE TRUE FALSE FALSE TRUE
[ 1 ] 31 41 31
[ 1 ] 11 21 31

На­вер­ное, единс­твен­ный ком­мента­рий, который тре­бует­ся к дан­ному при­меру, — это то, что опе­рация > работа­ет как век­торная опе­рация и резуль­татом ее выпол­нения будет век­тор булевых зна­чений, этот век­тор может быть исполь­зован для выбор­ки дан­ных из век­тора.

При работе с мат­рицами так­же не воз­ника­ет никаких слож­ностей, нуж­ные стро­ки и стол­бцы мы можем получить лег­ко и неп­ринуж­денно. К при­меру, запись x[ 2, 3] — это эле­мент во вто­рой стро­ке и в треть­ем стол­бце, а x[ 1, ] и z[, 2] — это пер­вая стро­ка и вто­рой стол­бец соот­ветс­твен­но. По умол­чанию эти опе­рации воз­вра­щают век­тор, а не мат­рицу, в которой одна стро­ка или стол­бец, и если мы хотим, что­бы резуль­татом выпол­нения дан­ной опе­рации была все‑таки мат­рица, пусть и дру­гого раз­мера, то нуж­но исполь­зовать допол­нитель­ный параметр x[ 1, , drop=FALSE] .

С дос­тупом к эле­мен­там спис­ка все нем­ного слож­нее. Рас­смот­рим сле­дующий при­мер:

> l < — list ( a = 0. 5 , b = 1 : 3 )
[ 1 ] «integer»

На этом при­мере дос­таточ­но хорошо вид­ны осо­бен­ности дос­тупа к эле­мен­там в R.

Как мож­но заметить, исполь­зование [[] ] не гаран­тиру­ет соот­ветс­твие типа воз­вра­щаемо­го зна­чения изна­чаль­ному, а в слу­чае оди­нар­ных ско­бок [ ] воз­вра­щаемое зна­чение так­же явля­ется спис­ком.

В этом смыс­ле $ и [[] ] работа­ют очень похоже. Хотя есть некото­рая осо­бен­ность — зна­чение в двой­ных квад­ратных скоб­ках может быть вычис­лено, а имя пос­ле зна­ка $ — нет.

Спис­ки быва­ют вло­жен­ными, и дос­туп к их эле­мен­там осу­щест­вля­ется с помощью вло­жен­ных ско­бок, как и полага­ется: x[[ 1]][[ 3] ] , одна­ко мож­но сде­лать запись чуть более понят­ной, исполь­зуя фун­кцию c . К при­меру, пос­леднее выраже­ние мож­но записать как x[[ c( 1, 3)] ] . При­чем исполь­зовать селек­тор с одной скоб­кой не получит­ся (подумай почему).

Управляющие структуры

На­до заметить, что в дан­ной статье я рас­смат­риваю R имен­но как язык прог­рамми­рова­ния, но на самом деле мож­но было бы взгля­нуть на него как на сис­тему для работы со ста­тис­тикой с типич­ными фун­кци­ями для решения пов­седнев­ных задач. Одна­ко я пред­почту быть кон­серва­тив­ным в изло­жении и, как полага­ется пос­ле опи­сания базовых типов, перей­ду к раз­говору об условных бло­ках и цик­лах.

Нач­нем с условно­го опе­рато­ра. Надо ска­зать, что здесь в R нет поч­ти ничего осо­бен­ного, но все‑таки:

if ( x > 0 ) < y < — x >else < y < — — x >

Ни­чего нового тут нет, и else может быть опу­щен. Хотя и тут не обош­лось без нес­коль­ко необыч­ного поведе­ния. В фун­кци­ональ­ных язы­ках, таких как Haskell, конс­трук­ция if явля­ется выраже­нием, а не опе­рато­ром, то есть воз­вра­щает зна­чение, а не изме­няет сос­тояние. В язы­ке R эта идея так­же наш­ла себе мес­то в сле­дующей конс­трук­ции:

y < — if ( x >0 ) < x >else < — x ># фигурные скобки можно опустить

Пос­ледняя конс­трук­ция дела­ет то же самое, что и пре­дыду­щая, толь­ко в фун­кци­ональ­ном сти­ле. Одна­ко в фун­кци­ональ­ных язы­ках выраже­ние дол­жно быть опре­деле­но и поэто­му наличие вет­ви else обя­затель­но. Здесь же это не так, конс­трук­ция z < — if ( x < 0) -x впол­не допус­тима, но зна­чени­ем это­го выраже­ния при x >0 будет спе­циаль­ное зна­чение NULL . Для срав­нения с этим зна­чени­ем мож­но исполь­зовать фун­кцию is. null .

Те­перь сто­ит ска­зать пару слов о цик­лах. Цик­лы в R работа­ют мед­ленно, но ког­да мы име­ем срав­нитель­но неболь­шой объ­ем дан­ных, то исполь­зование цик­лов может быть впол­не допус­тимо и даже удоб­но. С этой точ­ки зре­ния R так­же мало отли­чает­ся от дру­гих язы­ков прог­рамми­рова­ния. Нач­нем с цик­ла for , который реали­зует извес­тную парадиг­му for-in.

x < — c ( «a» , «b» , «c» , «d» , «e» )
for ( i in 1 : 5 ) <
print ( x [ i ] )
for ( ch in x ) print ( ch )

Как и полага­ется, цикл for-in реали­зует про­цесс ите­рации по век­тору или пос­ледова­тель­нос­ти, пос­ледний вари­ант более лакони­чен, одна­ко если нам каким‑либо обра­зом нуж­ны индексы, то хорошо бы иметь воз­можность соз­давать пос­ледова­тель­ность, соот­ветс­тву­ющую задан­ному век­тору.

Для это­го в R пре­дус­мотре­на спе­циаль­ная фун­кция seq_along , при­нима­ющая в качес­тве аргу­мен­та век­тор или спи­сок, для которых стро­ится пос­ледова­тель­ность индексов. Таким обра­зом, пер­вый цикл мож­но было бы перепи­сать в виде for( i in seq_along( x)) < . >. Для того что­бы сге­нери­ровать пос­ледова­тель­ность задан­ной дли­ны, мож­но вос­поль­зовать­ся фун­кци­ей seq_len .

Кста­ти, все эти воп­росы лег­ко решить извес­тны­ми средс­тва­ми, исполь­зуя лишь фун­кцию вычис­ления дли­ны length . Цикл while име­ет впол­не клас­сичес­кую фор­му while ( cond) < . >.

Ло­гичес­кие связ­ки в R так­же выг­лядят стан­дар­тным обра­зом: , || и ! . В допол­нение к баналь­ному while( TRUE) в R при­сутс­тву­ет небаналь­ный repeat < . >, выход из которо­го обес­печива­ет, как обыч­но, ком­бинация if и break . Для перехо­да к сле­дующей ите­рации пре­дус­мотрен опе­ратор с нес­коль­ко неожи­дан­ным наз­вани­ем next .

Как мож­но заметить, раз­делите­лей вро­де точ­ки с запятой меж­ду опе­рато­рами в R нет.

Функции

Как уж без фун­кций в при­лич­ном язы­ке прог­рамми­рова­ния? В самом общем виде опре­деле­ние фун­кции выг­лядит сле­дующим обра­зом:

Как и в фун­кци­ональ­ных язы­ках, фун­кции в R явля­ются объ­екта­ми клас­са. Это озна­чает, что их мож­но передать в качес­тве аргу­мен­та в дру­гую фун­кцию и вер­нуть в качес­тве зна­чения. Ано­ним­ные (лям­бда) фун­кции так­же при­сутс­тву­ют:

f < — function ( g ) <
function ( x ) g ( g ( x ) )
y < — f ( function ( x ) x * x ) ( 5 )

Здесь фун­кция f при­нима­ет в качес­тве аргу­мен­та фун­кцию g и воз­вра­щает фун­кцию, которая име­ет один фор­маль­ный параметр x и дваж­ды при­меня­ет к нему фун­кцию g . Так­же в коде мож­но уви­деть переда­чу ано­ним­ной фун­кции в качес­тве аргу­мен­та, а получен­ный резуль­тат (ком­позиция фун­кций g и самой себя) при­меня­ется к чис­лу 5. Таким обра­зом, чис­ло 5 будет дваж­ды воз­ведено в квад­рат.

По­рядок вычис­ления аргу­мен­тов в R явля­ется отло­жен­ным (lazy), то есть аргу­мент не вычис­ляет­ся, если он не нужен:

> f < — function ( x , y ) x * x
> f ( 3 , 5 / 0 )

Для того что­бы пра­виль­но работать с сос­тоянием в слу­чае замыка­ний, сущес­тву­ет опе­ратор

Источник: xakep.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru