Шипунов А.Б. n+1 вопрос про R [Электронный ресурс]. 2002. Режим доступа:
http://herba.msu.ru/shipunov/software/r/rplus1.htm
Shipunov A.B. n+1 question about R [Electronic resource]. 2002. Mode of access:
http://herba.msu.ru/shipunov/software/r/rplus1.htm
Эта статья не претендует на обучение основам статистики. Автор рассчитывает на читателя, более или менее знакомого с основными понятиями теории вероятностей и математической статистики. Такой читатель может научиться делать то, о чем он читал в руководствах, при помощи R.
Статистический анализ начинается с (1) постановки проблемы, продолжается (2) сбором данных, производится при помощи (3) обработки, и завершается (4) выводами. Здесь мы рассмотрим только третий этап. Нужно помнить, однако, что ``формулировка проблемы более важна, чем ее решение, которое является всего лишь математической или экспериментальной задачей'' (А. Эйнштейн).
Данные обрабатывают для того, чтобы извлечь из них информацию, недоступную ``невооруженному глазу''. Такая информация может быть очень различной, но чаще всего от обработки ожидают следующих результатов:
Самый простой способ - обрабатывать вручную или с помощью микрокалькулятора. Так и поступали до наступления эпохи компьютеров.
Способ посложнее - воспользоваться программами общего назначения, например, Excel. Однако реализация статистических функций в таких пакетах оставляет желать лучшего.
Самый сложный способ - научиться пользоваться специализированными статистическими программами. Таковых существует два сорта: (1) программы с интерфейсом меню и кнопок (SPSS, STATISTICA, MiniTab, StatGraphics) и (2) программы, общающиеся с пользователем в режиме команд (SAS, S-PLUS и R).
В начале 90-х годов в Bell Labs (там, где в свое время придумали Unix и C) изобрели язык, специально предназначенный для обработки данных. Этот язык назвали S. Затем фирма MathSoft, Inc. на основе этого языка разработала программу S-PLUS, которая успешно существует и по сей день (надо сказать, что статистические пакеты - долгожители компьютерного мира, например, SPSS развивается уже больше 30 лет!). В 1997 году группа энтузиастов задумала создать программу, аналогичную S-PLUS, но свободно распространяемую. Так появился R.
R - это среда для статистической обработки информации. ``Среда'' означает не просто набор программ, но и цельный, очень развитый язык программирования высокого уровня, который позволяет быстро и с удобством производить различные вычисления. Например, Вам нужно посчитать среднее для некоторой выборки (назовем ее x). R делает это в одно действие2:
> x # посмотрим, что это за выборка > [1] 1 2 3 4 5 6 7 8 9 # вот она > mean(x) # посчитаем среднее > [1] 5 # а вот и ответ
В общем-то, среднее для этой выборки можно посчитать и в уме. Но R позволяет подсчитывать гораздо более сложные вещи, такие как, например, вейвлет-преобразования, главные компоненты, дискриминантные функции и т.п. Это значит, что его можно использовать вместо широко употребляемых биологами программ для статистической обработки данных типа STATISTICA. Более того, по нашему мнению, это нужно делать. Вот несколько причин:
С другой стороны, хотя R и превосходно документирован, работа в нем происходит через так называемый ``интерфейс командной строки'', а привычные большинству пользователей кнопки и выпадающие меню практически отсутствуют.
Но сила R там же, где его ``слабость''. Интерфейс командной строки позволяет делать такие вещи, которых рядовой пользователь других статистических программ может достичь только часами ручного труда. Вот, например, простая задача: требуется превратить выборку x (см. выше) в матрицу из трех колонок (допустим, это были данные за 3 дня, а каждый день делалось 3 измерения). Чтобы сделать это в STATISTICA, требуется: (1) учредить две новые переменные, (2-3) скопировать дважды кусок выборки в буфер, (4-5) скопировать его в одну и другую переменную и (6) уничтожить лишние строки. В R это делается так:
> b <- matrix(x, ncol=3) # применим команду matrix() > b # посмотрим, что вышло [,1] [,2] [,3] [1,] 1 4 7 [2,] 2 5 8 [3,] 3 6 9
Вся работа в R происходит посредством команд. Команды вводятся вручную, но если какая-нибудь уже была введена раньше, то к ней всегда можно вернуться, нажав на клавиши со стрелками вверх (или вниз). Все команды имеют аргумент(ы), которые помещаются в круглые скобки. Даже команда выхода q() пишется с такими скобками.
Команды работают с объектами. Объекты могут относиться к самым различным типам, хотя б\'ольшая их часть по своей структуре бывает: (1) вектором (vector, factor), (2) матрицей (matrix, array), (3) перечнем (list), (4) таблицей данных (data.frame). С каждым объектом R обращается по-своему. Например, команда summary(), работает с любым типом объекта, но для каждого имеет особенный вывод.
Самый простой способ использования R - это арифметические вычисления. Например, выражение log(((sqrt(sum(c(2,2))))^2)*2.5) вычисляется так:
Как видите, круглые скобки можно вкладывать друг в друга. R раскрывает их, вычисляя значение ``изнутри наружу''.
Ясно также, для чего нужны сами круглые скобки. В них, как правило, пишутся аргументы команды. Этих аргументов может быть очень много, и один из самых простых способов узнать, какие той или иной команде требуются аргументы, это ввести команду args(команда). Например, команда round (``округлить'') имеет два аргумента: число, которое нужно округлить, и значение digits, сообщающее, до какого знака округлять. Система аргументов работает разумно, так что все равно, чт\'о написать:
> round(1.5, digits=0) [1] 2 > round(1.5, d=0) [1] 2 > round(d=0, 1.5) [1] 2 > round(1.5, 0) [1] 2 > round(1.5,) [1] 2 > round(1.5) [1] 2
Это происходит благодаря тому, что есть так называемые ``умалчиваемые'' значения аргументов. Нарпимер, в данном случае умалчиваемое значение аргумента digits - ``0''. Об этом говорит и результат вывода команды args():
> args(round) > function (x, digits = 0)
Можно заметить также, что некоторые аргументы имеют имена. В результате аргументы можно вызывать не по порядку, а по именам. Имена же можно сокращать вплоть до одной буквы, но только если нет разных аргументов, которые от такого сокращения станут неразличимы. Можно вызывать аргументы по порядку, через запятую3, и тогда разрешается не использовать имен.
Если Вы не знаете, как работает та или иная команда, надо вызвать помощь:
> help(rep)
или
> ?rep
Справочные файлы написаны очень хорошо (конечно, на английском языке) и почти всегда содержат примеры, которые можно ``запустить'' командой example().
Как получить объекты, описано в следующем разделе. Очень полезны команды ls() и rm(), которые нужны для того, чтобы просматривать и удалять существующие в памяти компьютера объекты4.
Сначала о том, как это сделать прямо в R. Можно, например, использовать команду c():
> a <- c(1,2,3,4,5) > a [1] 1 2 3 4 5
Здесь мы получаем объект a, состоящий из чисел от одного до пяти.
Можно использовать команды rep(), seq(), scan(), а также оператор двоеточия:
> b <- 1:5 > b [1] 1 2 3 4 5
Можно воспользоваться встроенной в R подпрограммой - электронной таблицей наподобие сильно упрощенного Excel:
> data.entry(b)
В этой таблице можно редактировать данные ``на месте'', то есть вс\"е, что Вы ввели, непосредственно скажется на содержании объекта. Это несколько противоречит общем концепциям, заложенным в R, и поэтому есть функция de(), которая не меняет объект, а выдает результат ``наружу''(как list). Если же у Вас уже есть таблица данных, можно использовать команды fix() или edit(), которые в данном случае вызовут тот же Excel-подобный редактор.
Функция edit(), вызванная для другого типа объекта, запустит его редактирование в текстовом редакторе (под Windows это обычно Notepad или Блокнот), и Вы можете отредактировать объект там. Если Вы хотите поменять редактор, напишите, например:
> options(editor="c:\\Program Files\\quickpad\\quickpad")
Однако лучше всего научиться загружать в R файлы, созданные при помощи других программ, скажем, при помощи Excel. Предположим, Вы работаете с файлом электронной таблицы, который содержит в первой строке названия переменных. Тогда надо:
После этого можно прочитать файл из R следующей командой:
> myfile <- read.table(file="myfile.dat", header=TRUE, sep=";")
Вы получаете объект myfile, который является таблицей данных. Имена переменных (их можно получить командой names(myfile)) берутся при этом из первой строки файла. Объект myfile похож на содержимое электронной таблицы (это можно увидеть, набрав в командной строке его название), но не хранит дополнительных данных7, например, о том, что означают те или иные переменные. Поэтому рекомендуется завести еще один файл, который будет содержать необходимые пояснения. Другой вариант - помещать необходимые комментарии в первых строчках файла после знака #, команда read.table() пропустит такие строки.
Если исходный файл будет устроен по-другому (например, без имен переменных), нужно лишь немного поменять значения аргументов. Главное, чтобы Ваш файл был текстовым и чтобы в нем присутствовали разделители везде, кроме концов строк. Обратите внимание, что такой файл можно получить в любом текстовом редакторе, а не только в программах для создания электронных таблиц.
Суммируя, можно сказать, что один из возможных способов работы с данными в R такой:
Такой способ несколько сложен, но позволяет использовать все преимущества программ по набору электронных таблиц и текстовых редакторов. Можно, конечно, поступить проще и вообще не использовать ничего, кроме R. Тогда есть два пути сохранения объекта между сессиями: либо (1) записывать его в виде текстового файла (см. выше), либо (2) сохранять как бинарный файл R. Второе требует использования либо команды save(), либо команды save.image(), причем последняя сохранит все объекты, накопленные Вами к текущему моменту8. Учтите, что бинарный файл проще сохранить и быстрее загрузить (командой load()), но его нельзя прочитать из других программ, а размер его значительно больше, чем у текстового файла.
Удобно принять соглашение, по которому все текстовые файлы данных, годные для загрузки в R, должны оканчиваться на *.dat, а бинарные файлы R должны оканчиваться на *.rd. Сразу скажем, что программы на языке R записываются в текстовые файлы, оканчивающиеся просто на *.r (а загружаются они командой source()).
Очень важная часть работы со статистическими данными заключается в преобразовании данных с целью обработки только какой-нибудь их части. Например, у нас есть файл carex.dat, устроенный следующим образом (пример создан искусственно):
SPECIES LENGTH WIDTH aqu 3.1 1.3 aqu 3.2 1.5 sal 2.5 NA rec 2.4 0.3 aqu 2.3 0.1 sal 2.1 0.8 sal 2.9 1.4
Допустим, мы хотим получить для обработки данные только по тем осокам, которые относятся к виду ``aqu'' (Carex aquatilis). Как это сделать?
> setwd("e:\\temp") # (1) NULL > carex <- read.table("carex.dat",h=T) # (2) > car.aqu <- carex[carex[,1]=="aqu",] # (3) > car.aqu # (4) SPECIES LENGTH WIDTH 1 aqu 3.1 1.3 2 aqu 3.2 1.5 5 aqu 2.3 0.1
Сначала (1) мы установили рабочую директорию, то есть директорию, в которой находится наш файл, затем (2) загрузили сам файл. Обратите внимание, что названия команд сокращены, а разделитель не указан, потому что по умолчанию он является пробелом. Получился объект (таблица данных) carex. Затем мы написали команду (3), которая означает:
создать объект car.aqu и поместить в него (<-) те строки из carex (carex[...,]), у которых в первой колонке (carex[,1]) есть строка ``aqu'' (==äqu")Команда (4) вывела содержание объекта car.aqu. Мы познакомились сразу с двумя типами выборок: числовыми и логическими. Числовая выборка - это, например, команда carex[,1], которая означает ``первая колонка таблицы carex''. Логическая - это команда carex[,1]==äqu". Если выполнить ее саму по себе, то получится:
> carex[,1]=="aqu" [1] TRUE TRUE FALSE FALSE TRUE FALSE FALSE
Мы получили ответ на вопрос: для каких строк верно, что в первой колонке написано ``aqu''? Ответ такой: ``для первой, второй и пятой''. Можно было бы написать:
> car.aqu <- carex[c(TRUE,TRUE,FALSE,FALSE,TRUE,FALSE,FALSE),] > car.aqu SPECIES LENGTH WIDTH 1 aqu 3.1 1.3 2 aqu 3.2 1.5 5 aqu 2.3 0.1
и получить тот же результат. Теперь попробуйте представить, что мы получим, если введем команду:
> carex[carex[,2]>2.7,]
Это будут те строки, значение второй переменной для которых больше 2,7. Ту же команду можно было записать по-другому:
> carex[carex$LENGTH>2.7,] SPECIES LENGTH WIDTH 1 aqu 3.1 1.3 2 aqu 3.2 1.5 7 sal 2.9 1.4
Еще одно применение таких преобразований состоит в том, что можно с легкостью заменить любые данные, опираясь на их логический или числовой ``адрес'':
> car.m <- car.aqu[,-1] # убираем колонку 1 > car.m <- as.matrix(car.m) # преобразуем таблицу в матрицу > car.m LENGTH WIDTH 1 3.1 1.3 2 3.2 1.5 5 2.3 0.1 > car.m[car.m>2] <- 1000 # заменяем числа, большие 2, на 1000 > car.m LENGTH WIDTH 1 1000 1.3 2 1000 1.5 5 1000 0.1
Заметим, что преобразовывать таблицу данных в матрицу следует, когда возникает нужда в подобных операциях замены. При этом нужно помнить, что матрица отличается от таблицы данных, в частности, тем, что ее столбцы должны иметь одинаковую природу - не могут сочетаться колонки, состоящие из цифр (numeric) и колонки, состоящие из букв (character). Обойти такой запрет можно, обрабатывая переменные по одной:
> car.aqu -> car.aqu.save > car.aqu$LENGTH[car.aqu$LENGTH>2] <- 1000 # (1) > car.aqu SPECIES LENGTH WIDTH 1 aqu 1000 1.3 2 aqu 1000 1.5 3 sal 1000 1.4 > car.aqu <- car.aqu.save # восстанавливаем сохраненное > car.aqu[[2]][car.aqu[[2]]>2] <- 1000 # то же, что (1) > car.aqu SPECIES LENGTH WIDTH 1 aqu 1000 1.3 2 aqu 1000 1.5 3 sal 1000 1.4 > car.aqu <- car.aqu.save > len <- car.aqu$LENGTH # еще один вариант > len[len>2] <- 1000 > car.aqu$LENGTH <- len > car.aqu SPECIES LENGTH WIDTH 1 aqu 1000 1.3 2 aqu 1000 1.5 3 sal 1000 1.4 > rm(len)
В начале надо выяснить несколько вопросов:
Первый вопрос наиболее важен - от его решения зависит весь стиль работы. В общем случае, статистические данные могут быть трех различных типов:
Второй вопрос особенно важен для многомерных методик. Нельзя (за редким исключением некоторых методов вычисления сходства) одновременно работать с данными, измеренными в разных единицах! Если в таблице присутствуют и метры, и килограммы, обычные многомерные статистические методы (типа анализа главных компонент) не годятся9.
Третий вопрос особенно важен в тех случаях, когда предполагается использовать так называемые параметрические методы. Эти методы рассчитаны на то, что данные имеют нормальное (гауссово) распределение10, а иногда (как базовый t-тест или дискриминантный анализ) еще и на то, что разброс (варианса) сравниваемых выборок одинаковы. Понятно, что ни дискретные, ни тем более категориальные данные не попадают в сферу параметрической статистики. С другой стороны, существуют и активно развиваются непараметрические методы, например, ранговые статистики, многомерное шкалирование, бутстреп и т.д. Поэтому данные надо обязательно проверить ``на нормальность''!
Четвертый вопрос также очень важен. Выбросы (данные, сильно отклоняющиеся от общей массы), пропущенные значения (``пустые клетки'') и просто опечатки могут коренным образом исказить результаты анализа. Чтобы этого не произошло, нужно обязательно выяснить структуру анализируемого в R объекта и посчитать базовые статистики.
Структура выясняется командой str(). Ее вывод обычно позволяет понять, в каком режиме будут обрабатываться переменные. Нарпимер, если переменная LENGTH выдается как factor - что-то не в порядке, и нужно обязательно выяснить, нет ли опечаток в тексте файла (скажем, один случайно набранный дефис может привести к тому, что вся колонка будет трактоваться как фактор).
Базовыми, или описательными, статистиками называют обычно общие характеристики данных, например, среднюю величину. Разумеется, в R существуют для этого специальные функции:
> mean(carex[,2]) # среднее [1] 2.642857 > median(carex[,2]) # медиана [1] 2.5 > mean(carex[,3]) # не получается! [1] NA > mean(carex[,3], na.rm=TRUE) # надо не учитывать NA [1] 0.9 > sd(carex[,3], na.rm=T) # стандартное отклонение [1] 0.5966574
В этом примере используется тот же объект carex, что и в предыдущем разделе. Как видно, нам сильно помешал NA в третьей строке третьей колонки. Дело в том, что таким образом в R обозначаются пропущенные данные. ``Пустое место'' может возникнуть по тысяче причин - от неаккуратного наблюдения и потери данных до невозможности измерить данный признак (например, экземпляр поврежден).
Очень просто получить описательные статистики одной командой:
> summary(carex) SPECIES LENGTH WIDTH aqu:3 Min. :2.100 Min. :0.100 rec:1 1st Qu.:2.350 1st Qu.:0.425 sal:3 Median :2.500 Median :1.050 Mean :2.643 Mean :0.900 3rd Qu.:3.000 3rd Qu.:1.375 Max. :3.200 Max. :1.500 NA's :1.00
Как видно, вместо стандартного отклонения здесь приведены медиана (значение, которое делит наблюдения пополам) и квартили (между ними должно попадать 50% значений), что гораздо удобнее для таких данных, которые не имеют нормального распредениеия и/или имеют длинные ``хвосты''.
Заметьте, что статистики по первой переменной сильно отличаются. Это потому, что она ведет себя как фактор, то есть буквенный вектор, имеющий несколько уровней (в данном случае уровней три). Проверим это (кодами уровней называют числовые значения, связанные с уровнями фактора.):
> is.factor(carex$SPECIES) # фактор ли это? [1] TRUE # да! > levels(carex$SPECIES) # показать уровни [1] "aqu" "rec" "sal" > codes(carex$SPECIES) # показать коды уровней [1] 1 1 3 2 1 3 3
И все-таки, NA в третьей колонке будет все время мешать в дальнейших вычислениях. Хорошо бы его заменить на что-нибудь более ``операбельное''! Вот как заменить его на медиану:
> is.na(carex$WIDTH) # какие данные пропущены? [1] FALSE FALSE TRUE FALSE FALSE FALSE FALSE > carex$WIDTH[is.na(carex$WIDTH)] <- median(carex$WIDTH) > carex$WIDTH [1] 1.3 1.5 NA 0.3 0.1 0.8 1.4 # не получилось! > carex$WIDTH[is.na(carex$WIDTH)] <- median(carex$WIDTH, na.rm=T) > carex$WIDTH [1] 1.30 1.50 1.05 0.30 0.10 0.80 1.40 # получилось!
Иногда возникает потребность посчитать что-либо для каждой колонки. Вот как посчитать, например, сумму чисел во всех строках нашего объекта:
> apply(carex[,-1],1,sum) 1 2 3 4 5 6 7 4.40 4.70 3.55 2.70 2.40 2.90 4.30
Если бы мы вторым аргументом указали ``2'', то R посчитал бы сумму по колонкам. А теперь посчитаем основные статистики для LENGTH, но по каждому виду - отдельно:
> tapply(carex[,2],carex$SPECIES,summary) $aqu Min. 1st Qu. Median Mean 3rd Qu. Max. 2.300 2.700 3.100 2.867 3.150 3.200 $rec Min. 1st Qu. Median Mean 3rd Qu. Max. 2.4 2.4 2.4 2.4 2.4 2.4 $sal Min. 1st Qu. Median Mean 3rd Qu. Max. 2.1 2.3 2.5 2.5 2.7 2.9
Такая операция экономит массу времени, затрачиваемое в обычных пакетах на вырезание, копирование, построение подмножеств и пр.
В R встроен обширный набор графических функций и значительный набор функций для сохранения графиков в различных форматах. Поэтому вставить график из R в статью, набирающуюся в LATEX или MS Word, достаточно легко11.
Приведем несколько важных соображений по поводу графиков. Первое касается оформления. Все элементы оформления определяются в аргументах соответствующей графической команды. Вот, например, команда для построения гистограммы:
> hist(carex[,2], main="Sample histogram", xlab="LENGTH", col="gray")
Второе соображение касается способа работы с уже построенным графиком. Графические команды делятся на две группы: команды первой группы (например, plot(), hist(), boxplot(), pairs()) заменяют построенный график новым, а команды второй (например, lines(), points(), text()) добавляют к имеющемуся графику новые элементы (к сожалению, стирать нельзя). Вот как добавить текст в произвольное место уже построенного графика:
> text(locator(), "Sample\n text", cex=.8)
Функция locator() работает по щелчку левой кнопкой мыши и выдает две координаты точки щелчка. Затем надо щелкнуть правой кнопкой и в появившемся меню выбрать ``Stop''. Тотчас же на месте щелчка появится текст, разделенный командой \n на две строки. Аргумент cex изменяет относительный размер шрифта.
Третье соображение касается того, как сохранять графику в файлах. Проще всего это делать через изменение графического устройства (graphic device). Вот как ту же гистограмму сохранить в файл с расширением *.png:
> png(file="rplus1.png", width=480, height=480) > hist(carex[,2], main="Sample histogram", xlab="LENGTH", col="gray") > dev.off()
Первая команда ``открывает'' графическое устройство (в данном случае файл rplus1.png), а третья - закрывает его, записывая график в файл. Вторая команда ничего не выдает на экран, поскольку графическим устройством в этот момент является файл.
Другой способ сделать это - при помощи команды dev.print(). Преимущество последнего способа в том, что Вы можете сохранить в файл все содержимое текущего графического окна, в том числе и элементы, нанесенные при помощи интерактивных команд locator() и identify().
Еще одно соображение касается настройки. Почти все параметры выводимых графиков настраиваются, но это иожет потребовать больших усилий. К счастью, R, как правило, предоставляет очень разумные подборки параметров. В любом случае общая настройка происходит через команду par():
> oldpar <- par(mfrow=c(2,2), bg="white") ... > par(oldpar)
Здесь мы поменяли цвет фона (это полезно для сохранения графики командой dev.print()) и количество графиков в окне, а затем вернулись к сохраненному старому значению параметров (bg="transparent", mfrow=c(1,1)).
R предоставляет большой выбор статистических тестов. Из параметрических в общем случае наиболее полезны t.test(), а из непараметрических - wilcox.test() и chisq.test(). Второй тест можно вызвать также командой summary(table(f1,f2)), где f1 и f2 - некоторые факторы. Выдаваемое ими значение p-value относится к вероятности нулевой гипотезы.
Результат работы теста - это обычно каким-то образом оформленный перечень (list). Поэтому легко вызвать отдельные компоненты теста, просто указав на них при помощи операторов $ либо [[]].
Для выявления взаимосвязей обычно используются коэффициенты корреляции, а также регрессионный анализ. Все это (а также многое другое) реализовано в R. При вычислении корреляций (функция cor()) нужно не забывать убирать строки с пропущенными значениями (например, при помощи na.omit()), а также заменять факторы на их коды.
Класификация подразумевает работу с многомерными данными, то есть сразу с несколькими векторами (столбцами). Основная коллекция многомерных методов находится в дополнительно загружаемом пакете mva:
> library(mva)
В этом пакете реализованы, в частности, создание матриц сходства (dist()), метрическое многомерное шкалирование (cmdscale()), анализ главных компонент (princomp()) и иерархический кластерный анализ (hclust()). Неметрическое многомерное шкалирование реализовано в пакете MASS (называется isoMDS()), очень много методов кластеризации собрано в пакете cluster (функции daisy(), diana() agnes()). Очень интересны также пакеты tree и rpart, которые вводят одноименные функции, предназначенные для построения деревьев классификации (метод, гораздо более мощный, чем распространенный дискриминантный анализ). Кроме того, имеется специализированный пакет vegan, в котором собрано много популярных в экологии индексов сходства (например, индекс Жаккара, функция vegdist(..., method="kulczynski")) и многомерных методов (например, decorana()). Добавим теперь несколько замечаний относительно распространенных многомерных методов.
Для этого важно время от времени сохранять файл истории команд командой savehistory(). После этого получившийся файл можно редактировать в любом текстовом редакторе, убирая ненужные и ошибочные команды. Теперь, если Вы хотите повторить анализ, нужно сделать так:
> sink("my.out") > source("myhistory.r", echo=T) > sink()
Если Ваши команды записаны в файл myhistory.r, то все они будут выполнены (учтите, что любая ошибка прервет исполнение), а все результаты записаны в файл my.out. Естественно, если Вы создавали какие-либо графические файлы, то они будут созданы заново. И отчет готов!
1© А. Шипунов, 2002. Каждый имеет право воспроизводить, распространять и/или вносить изменения в настоящий документ в соответствии с условиями GNU Free Documentation License, версией 1.1 или любой более поздней версией, опубликованной Free Software Foundation. Данный документ не содержит неизменяемых разделов, а также текста, помещаемого на первой и последней страницах обложки. Копия настоящей лицензии находится по Internet-адресу http://www.gnu.org/copyleft/fdl.html.
2# - это символ комментария, и все, что за ним, R не читает. Подразумевается, что в конце каждой строки, начинающейся с >, была нажата клавиша <ENTER>.
3Кстати, учтите, что для десятичных дробей используется точка!
4R не использует никаких вр\'еменных файлов, вся информация об объектах хранится в памяти. Чтобы записать объекты на диск, воспользуйтесь командами типа save() (см. ниже).
5Это потому, что в русифицированных программах принято в качестве десятичного разделителя использовать запятую, и программа потом может перепутать, где какой разделитель.
6Excel выполняет этот пункт, если вы сохраняете данные в формате CSV.
7Пока Вы этого специально не захотите, см. команду attributes().
8Их список, если Вы не забыли, можно получить командой ls().
9Фраза ``не годятся'' звучит, может быть, чересчур жестко. В общем случае она означает, что таких методов надо избегать, поскольку их результаты могут оказаться содержательно не интерпретируемыми. Возможно, однако, применять их на свой страх и риск.
10Такое распределение возникает, например, если стрелять в цель, а затем измерять расстояние от центра мишени до каждого попадания.
11Хотя по соображениям
переносимости мы не будем демонстрировать в этом тексте
графики.