Из SPSS в R: различия между версиями

Содержимое удалено Содержимое добавлено
м →‎См.также: простановка шаблона "по алфавиту" по запросу на Форуме с помощью AWB
орфография, викификатор
Строка 1:
Здесь представлен перевод статьи [mailto: dusa.adrian@gmail.com Adrian Duşa] [http://wiki.r-project.org/rwiki/doku.php?id=getting-started:translations:spss2r 'From SPSS to R']
 
== О чем эта статья ==
Когда я только начал использовать [[w:R (язык программирования)|R]], мне потребовалось узнать ответы на те вопросы, которые раньше для меня таковыми не являлись, например:
* где же мои данные?
* м-м-м, как я могу установить метки значений?
* и мне действительно необходима возможность устанавливать метки переменных!
* (почесывая затылок) а теперь как я могу отсортировать данные, если здесь нет возможности нажать на переменной правой кнопкой мыши?
* постойте, как же я смогу создавать те выходные таблицы с потрясающим форматированием?
* и как я могу скопировать и вставить результат в текстовый редактор Word?
* формат файлов SPSS - — .sav; как сохранять данные в R?
* и многое-многое другое...другое…
 
Звучит знакомо? Думаю, да. Хорошо...Хорошо… давайте рассмотрим все внимательно и по порядку.
 
Во-первых, переход на R — это изменение в восприятии. Видеть данные — это похоже на наркотическую зависимость, от которой нужно избавится: вам не нужно их видеть. И вы их, действительно, не видите, поскольку то, что предлагает [[w:SPSS|SPSS]] — это только маленький прямоугольный кусочек от большого массива. Эта маленькая зрительная хитрость, которую вы можете осуществить и в R с использованием простых команд.
 
Нам нужен экспериментальный массив данных; скажем, вот этот:
Строка 23:
!AGE
|-
! 1
| 2
| a
| 42
|-
!2
| 1
| a
| 18
|-
!3
| 3
| b
| 49
|-
!4
| 2
| a
| 62
|-
!5
| 1
| b
| 25
|}
 
Строка 79:
Хорошо, далее несколько команд SPSS, выполнение которых в R может быть вам интересным.
 
== Сортировка наблюдений ==
Мы хотим отсортировать наши данные в возрастающем порядке по переменной ONE:
<code>
Строка 86:
 
Ключ к пониманию этой команды (звучит как введение в R, но по вопросу основ лучше прочить руководство «[http://m7876.wiki.zoho.com/Introduction-to-R.html Введение в R]») лежит в том, как R индексирует строки и столбцы. Существует два ключевых инструмента, которые делают такую сортировку:
* функция <code>order()</code>, смотрите справку через команду <tt>?order</tt>;
* содержимое, заключенное в квадратные скобки.
 
Квадратные скобки содержат информацию для индексирования: перед запятой указана индексация для строк, после запятой — для колонок. Функция, помещенная перед запятой, указывает на то, что мы хотим сделать со строками нашего массива (и это именно то, что мы хотим сделать: отсортировать наблюдения, т.е.то есть строки).
 
Мы можем захотеть отсортировать данные в убывающем порядке:
Строка 107:
</code>
 
<code>order()</code> возвращает вектор индексов. Последний символ в нашем векторе — это «<tt>а</tt>» (пятая позиция), которая в векторе, возвращенным функцией <code>order()</code>, находится на пятой позиции (число 5 возвращается первым). И так далее:
 
<code><pre>> letter.vector[order(letter.vector)]
Строка 116:
Сортировка наблюдений массива данных имеет отношение к индексации; поэтому мы используем для этой цели функцию <code>order()</code>. Кажется несколько противоречащим здравому смыслу не использовать <code>sort()</code> для сортировки строк, но как только вы к этому привыкните, вы сразу почувствуете это естественным.
 
== Фильтрация наблюдений ==
Это очень просто: мы можем индексировать массив данных используя «[ , ]».
 
Строка 141:
1 2 a 42</pre></code>
 
== Метки значений ==
Существует огромная разница между SPSS и R в подходе к категориальным переменным. Не кажется ли странным, что приложение стоимостью в несколько тысяч долларов, как, например, SPSS, даже не пытается вывести предупреждение, когда кто-либо высчитывает арифметическое среднее номинальной переменной? Невероятно...Невероятно…
 
В R категориальная переменная называется фактор (<tt>factor</tt>). Номинальная переменная — это неупорядоченный (<tt>unordered</tt>) фактор, а порядковая переменная — это упорядоченный (<tt>ordered</tt>) фактор.
 
Категории номинальных и порядковых переменных называются уровнями (<tt>levels</tt>).
Строка 153:
Levels: a b</pre></code>
 
Ага...Ага… уровни (наши «метки») уже здесь. У нас есть два уровня: «a» и «b». Теперь давайте предположим, что переменная TWO обозначает пол: двумя категориями «мужчина» («male») и «женщина» («female»). Мы легко можем поменять наши «метки»:
<code><pre> > levels(test$TWO) <- c("male", "female")
> test$TWO
Строка 163:
Warning message:
argument is not numeric or logical: returning NA in: mean.default(levels$TWO)</pre></code>
"«Аргумент не является числовым или логическим"». Точка.
 
Вы можете подумать, что использование меток вместо номеров — это глупо (правда, и я думал также). Почему кто-то захочет так делать? Когда мы вводим данные, мы используем цифры, а не буквы. Так в чем же загвоздка? Дело в том, что то, что вы видите на экране — это совсем не то, что сохранено в базе данных. Хранилище (если я не ошибаюсь) состоит из чисел, R только печатает на экране уровни по умолчанию.
 
Давайте попробуем следующим образом:
<code><pre> > as.numeric(test$TWO)
[1] 1 1 2 1 2</pre></code>
Так...Так… мужчины — это 1, женщины — 2.
 
Возвращаясь к нашей проблеме: если у нас есть переменная, введенная в числовой форме (как переменная ONE), то первое, что мы должны сделать - — это объявить ее фактором (допустим, что наша переменная принимает три возможных значения, т.е.то есть имеет три категории):
<code>
<pre> > test$ONE <- factor(test$ONE, ordered = TRUE)
Строка 179:
Levels: 1 < 2 < 3</pre></code>
 
Обратите внимание на знаки "«меньше"» ("«<"») между уровнями: их наличие говорит нам о том, что переменная является порядковой.
 
Теперь давайте присвоим нашей переменной метки значений, используя любой из приведенных способов:
Строка 192:
Levels: Low < Medium < High</pre></code>
 
== Метки переменных ==
Это еще проще, чем метки значений. Мне известно о двух способах.
 
Строка 199:
<code><pre>attr(test$TWO, "label") <- "Пол респондента"</pre></code>
 
Мы только что присвоили переменной TWO дополнительный аттрибут под именем "«label"» (имя не играет никакой роли и могло быть другим, например "«varlab"»). Теперь давайте запросим метку (label) переменной TWO:
 
<code><pre> > attr(test$TWO, "label")
Строка 214:
[1] "Пол респондента"</pre></code>
 
== Создание таблиц ==
Здесь трудно аргументировать, но эта задача, возможно, потребует от вас больше усилий, чем вы можете предполагать. Но, поскольку вы уже ступили на дорогу R и открытых исходников, почему бы не пойти до конца?
 
Строка 221:
* каким легким способом таблицу можно вставить в документ?
 
Это может прозвучать неубедительно, но...но… вам не нужны таблицы с форматированием в стиле SPSS. Проблема действительно в этом: таблицы SPSS слишком "«заформатированы"». Слишком много выделений, слишком много линий, слишком много прямоугольников. Все это так притягательно, что отвлекает внимание от главного в таблице - — числа в ней.
 
Позвольте задать вам один вопрос: как много вы встречали публикаций с таблицами, отформатированными в стиле SPSS? Я попробую угадать и скажу: ни одной. Профессиональные журналы используют очень простое форматирование для таблиц, всего лишь несколько линий, чтобы разделить важное содержимое. Такие таблицы могут быть созданы с использованием специального программного обеспечения, например [http://ru.wikipedia.org/wiki/LaTeX LaTeX].
Строка 248:
* Для [http://ru.wikipedia.org/wiki/OpenOffice.org OpenOffice.org] существует другой замечательный пакет под названием [http://cran.r-project.org/web/packages/odfWeave/index.html odfWeave], который выполняет ту же саму задачу, что и <code>Sweave()</code>, но в документе OpenOffice. Вам даже не требуется копировать и вставлять таблицы или диаграммы: просто напишите код программы R в своем документе, пропустите его через R (да-да, R может так сделать) и на выходе вы получите новый документ [http://ru.wikipedia.org/wiki/ODF ODF] с таблицами и диаграммами именно в тех местах, где вы написали код.
 
Ну а если вдруг мне захочется создать в LaTeX точную копию таблицы SPSS, то я создам матричный объект (назовем его ONE), подобный этому:
<code>
<pre> Frequency Percent Cumulative\nPercent
Строка 263:
Запускаем полученный код в LaTeX и получаем таблицу:
 
[[ИзображениеФайл:Latexfreq.gif]]
 
Аккуратно, не правда ли? Это тот самый вид таблиц, который мы привыкли видеть в профессиональных журналах.
 
Если вам нужны еще аргументы, то следующий факт точно убедит вас: в SPSS есть одна вещь, которую вы можете сделать с таблицой - — это вставить ее в текстовый документ. Как красивую картинку. В R каждая таблица может быть определена как отдельный объект, из которого можно вытягивать любую информацию. У вас есть динамический доступ к любому и каждому числу внутри в любое время. Ну как?
 
== Перекодировка переменных ==
Это то же самое, что создать одну переменную на основе значений другой переменной; и перекодировка в ту же переменную тоже проста.
 
=== В другую переменную ===
==== Используя индексирование ====
Предположим, мы хотим перекодировать переменную AGE в три категории: "«Молодой"», "«Взрослый"», "«Пожилой"». Мы создаем переменную AGEREC, значения которой по умолчанию являются пропущенными. Поскольку эта переменная у нас порядкового уровня, мы можем объявить ее таковой через функцию <code>ordered()</code>:
 
<code><pre>test$AGEREC <- ordered(NA, levels = c("Young", "Adult", "Aged"))</pre></code>
 
Порядок уровней берется из очередности, в которой мы их указали (Уровень "«Молодой"» будет первым).
 
Теперь мы просто используем мощь индексации, заложенной в R.
Строка 285 ⟶ 286 :
test$AGEREC[test$AGE > 60] <- "Aged"</pre></code>
 
==== Используя функцию cut() ====
Существует несколько способов достичь одного и того же результата. Один из них - — это использование функции <code>cut()</code>. Допустим, у нас нет респондентов старше 100 лет.
<code>
<pre> > test$AGEREC <- cut(test$AGE, breaks = c(0, 35, 60, 100))
Строка 300 ⟶ 301 :
Levels: Young < Adult < Aged</pre></code>
 
==== Используя функцию recode() ====
Еще один способ сделать то же самое, это использовать функцию <code>recode()</code> из пакета [http://cran.r-project.org/web/packages/car/index.html car].
<code><pre> > library(car)
Строка 306 ⟶ 307 :
> test$AGEREC
[1] "Adult" "Young" "Adult" "Aged" "Young"</pre></code>
Обратите внимание, что переменная, полученная в результате, не является фактором (не все символьные переменные имеют тип "«фактор"»). Мы можем использовать аргумент <tt>as.factor.result</tt> функции <code>recode()</code>, но по умолчанию это создаст уровни, упорядоченные по алфавиту, нам же больше понравится, если уровень "«Молодой"» будет первым.
 
Традиционное решение - — это объявить переменную упорядоченным фактором:
<code><pre> > test$AGEREC <- ordered(test$AGEREC, levels = c("Young", "Adult", "Aged"))
> test$AGEREC
Строка 314 ⟶ 315 :
Levels: Young < Adult < Aged</pre></code>
 
=== В ту же переменную ===
Здесь трудно добавить что-то новое. Просто с левой и правой стороны оператора присваивания "«<-"» мы используем имя одной и той же переменной:
<code><pre>test$AGE <- cut(test$AGE, breaks = c(0, 35, 60, 100))
# or
Строка 338 ⟶ 339 :
Естесственно, все остальные приемы с уровнями и упорядочиванием остаются в силе.
 
== Пропущенные значения ==
...
 
== Как сохранять в формате R? ==
Как вы уже (к настоящему моменту) знаете, R предоставляет большое количество типов объектов: скаляры, вектора, матрицы, фреймы (dataframe), списки, массивы и ряд других (если я не ошибаюсь, то даже среда R может рассматриваться как объект).
 
Строка 349 ⟶ 350 :
 
Согласно информации, полученной при помощи команды <code>?data</code>, существует четыре поддерживаемых формата данных со следующими расширениями:
# "«.R"», "«.r"»;
# "«.RData"», "«rda"»;
# "«.tab"», "«.txt"» или "«.TXT"»;
# "«.csv"», "«.CSV"».
Но этот список не является обязательным к исполнению. Можно назвать файл любым именем с любым расширением, потому что при чтении этого файла будет необходимо указать полное имя, включая расширение.
 
Обычно, файлы, содержащие код R (т.е.то есть последовательность команд для выполнения), имеют расширение "«.R"».
 
Еще одно важное замечание: так как R может работать сразу с множеством объектов в памяти одновременно (представьте сразу два загруженных в память массива данных SPSS), он так же позволяет записывать неколько объектов в один файл.
Строка 362 ⟶ 363 :
 
Нижеследующие примеры являются базовыми, существует масса дополнительных опций, которые позволяют задать дополнительные параметры при сохранении ваших файлов. Не стесняйтесь обращаться к файлам справки по приведенным ниже функциям.
 
=== dump() и source() ===
Функция <code>dump()</code> записывает комбинацию команд (например, такие, как мы использовали для создания нашего пробного массива) и внутреннюю структуру массива данных.
 
Код R обычно записывается файлы с расширением "«.R"», поэтому мы выбирем такое же расширение:
<pre>dump("test", "test.R")</pre>
На следующем шаге мы можем использовать команды из файла "«test.R"» с использованием функции <code>source()</code>:
<pre>source("test.R")</pre>
На диске файл "«test.R"» записан в обычном текстовом формате, поэтому он вполне читаем. Вы можете посмотреть на него, чтобы понять принцип работы <code>dump()</code>.
 
=== save() и load() ===
Этот способ сохранения объектов R наиболее надежен, и именно его я рекомендую для применения. В данном случае информация записывается в двоичном формате, и поэтому файлы нечитабельны человеком.
 
Большое достоинство функции <code>save()</code> - — это маленький размер получаемых файлов. Они могут быть дополнительно сжаты (или путем применения аргумента "«<tt>compress</tt>"», или последующего сжатия утилитой gzip), и R без каких-либо проблем прочтет эти файлы.
 
Синтакс функции очень прост:
Строка 386 ⟶ 388 :
<code><pre>save.image("2006_09_25.Rdata")</pre></code>
 
=== dput() и dget() ===
Функция <code>dput()</code> делает практически то же самое, что и <code>dump()</code>, но с одним отличием: результатом выполнения функции не являются инструкции R. Результат содержит в себе только внутренннюювнутреннюю структуру объекта.
<code><pre>dput(test, "test.Rdput", control = "all")</pre></code>
Здесь мы использовали расширение имени файла "«<tt>.Rdput</tt>"» (расширение может быть любым). Очень полезно использовать аргумент <tt>control = "all"</tt>: это даст гарантию, что внутренняя структура объекта будет записана в файл полностью (включая все атрибуты объекта).
 
Считываем данные с диска:
<code><pre>test <- dget(test, "test.Rdput")</pre></code>
Еще одно отличие от команды <code>dump()</code> - — это явное создание объекта, когда в предыдущем варианте создание объекта происходит через инструкции, записанные в файл.
 
=== write.table() и read.table() ===
Функция <code>write.table()</code> создает [http://ru.wikipedia.org/wiki/ASCII ASCII]-представление массива данных, расширение имени выходного файла — - "«.tab"», "«.txt"» или "«.csv"» в зависимости от вида заданного разделителя (аргумент <tt>sep</tt>).
 
Выходной файл потеряет всю внутреннюю структуру объекта, т.е.то есть по нему мы не сможем судить, является ли переменная фактором, или упорядоченным фактором и  т. д.
 
Для файлов, разделенных табуляцией, инструкция будет следующей:
<code><pre>write.table(test, "test.tab", sep = "\t", row.names = FALSE)</pre></code>
Обычно, данные формата SPSS не имеют названий строк (подобно именам переменных). R, со своей стороны, такие имена содержит (еще одна причина предпочесть R), поэтому, если вы хотите получить имена переменных, установите значение соответсвующегосоответствующего аргумента (header) в <tt>TRUE</tt>.
 
ФукнцияФункция <code>read.table()</code> одна из самых полезных, она имеет множество аргументов. Минимальная форма применения следующая:
<code><pre>read.table("test.tab", header = TRUE, sep = "\t")</pre></code>
Для файла со значениями, разделенными запятыми, команда такая же, только аргумент <tt>sep</tt> меняется:
<code><pre>write.table(test, "test.tab", sep = ",")</pre></code>
 
=== write() ===
Функция используется для быстрой записи в файл вектора или матрицы.
 
Строка 420 ⟶ 422 :
Выходной файл не содержит имен строк и столбцов.
 
=== .saveRDS() и .readRDS() ===
Данный подход рекомендуется для смелых пользователей.
 
Строка 427 ⟶ 429 :
Иногда возникает ситуация, когда необходимо сохранить объекты R в базе данных, подобных [http://ru.wikipedia.org/wiki/MySQL MySQL]. Обычно это связано с тем, что массив данных очень большой.
 
Эта операция проста для массивов данных (dataframe) - — они имеют структуру, подобную структуре баз данных. Для более сложных объектов, например, списки или даже матрицы, такое прямое сохранение просто невозможно.
 
R может преобразовать любой свой объект в двоичную форму, как в формат [http://ru.wikipedia.org/wiki/BLOB BLOB] (большой бинарный объект) или его ASCII-представление. Это преобразование называется
[http://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F сериализацией] и оно дает большое преимущество, т.к.так как сериализованный объект - — это ничто иное, как простой вектор (как колонка в таблице MySQL).
 
Чтобы сериализовать объект, используйте функцию <code>serialize()</code>, чтобы обратить сериализованный объект в нормальное состояние, используйте <code>unserialize()</code>.
Строка 443 ⟶ 445 :
и теперь вы можете просмотреть структуру объекта, используя любой текстовый редактор.
 
== См. также ==
* [[Язык программирования R]]
 
Для более детальной информации о R на русском языке смотрите:
* [http://m7876.wiki.zoho.com/Introduction-to-R.html Перевод "«Введение в R"»]
* [http://m7876.wiki.zoho.com/R-Installation-and-Administration.html Перевод "«Установка и администрирование R"»]
* [http://linux.org.ru/jump-message.jsp?msgid=1627564 Методичка по системе статистич. анализа R]
* [http://herba.msu.ru/shipunov/software/r/rplus1.htm Шипунов А. Б. n+1 вопрос про R. 2002.]
* [http://herba.msu.ru/shipunov/software/r/rtips-ru.htm Шипунов А. Б.  Советы по R. 2002.]
* [http://herba.msu.ru/shipunov/software/r/r-ru.htm Каталог учебно-методических материалов по R Шипунова А. Б.]
 
{{Темы|Математика}}