Как сделать таблицу в r studio
В базовом пакете base есть функция read.table , которая отвечает за чтение текстовых файлов. Она имеет множество параметров, что позволяет гибко управлять процессом чтения. Эта функция возвращает data.frame.
При написании команд и функций удобно пользоваться возможность автодополнения. Для этого наберите часть команды, или имени функции или параметра и нажмите сочетание клавиш Ctrl+Пробел. В выпадающем списке можно выбрать подходящую команду.
При написании путей к папкам и файлам можно использовать либо абсолютный либо относительный путь. Например, предыдущий вызов можно оформить как
Для представления пути используются либо символы слэша (/) либо удвоенные символы обратного слэша (\). Это обусловлено тем, что обратный слэш в R это спецсимвол и добавление второго слэша его экранирует и указываает R, что следующий за ним символ надо вопринимать как обычный.
Т.е. обе эти записи пути эквивалетны: "D:/Teaching/R/introduction/md/data/sol_y1.txt" или "D:\\Teaching\\R\\introduction\\md\\data\\sol_y1.txt"
Посмотрим на данные, которые были загружены. Сделать это можно несколькими способами, вот некоторые из них
Функция read.table является не очень эффективной с точки зрения производительности. Файлы, содержащие большое число столбцов считываются очень медленно. Если попробовать прочитать файл sol_x1.txt , который содержит 4058 дескрипторов для 800 соединений, то это займет заметное время.
Можете попробовать выполнить следующий код
Для преодоления этого недостатка есть несколько вариантов, вот два из них:
1. Использовать экспериментальную функцию fread из пакета data.table .
2. Конвертировать текстовые файлы в бинарный формат и в дальнейшем работать с этими файлами.
Чтение текстовых файлов с использованием функции fread (пакет data.table)
Для просмотра загруженной таблицы в RStudio можно использовать команду
или кликнуть по имени переменной x1 в списке
Результат в обоих случаях будет одинаковым
Проверим объект какого класса получился при загрузке таблицы с использованием функции fread
Приведем объект x1 к типу data.frame
Отметим, что первая колонка содержит названия соединений. Переместим значения этой колонки в поле rownames
Проверим, что получилось.
Сохранение данных в бинарном формате
Любые объекты созданные в R можно сохранить в бинарном формате в виде файлов .RData . Это позволяет осуществлять быструю загрузку и доступ к сохраненным данным.
Таким образом можно сохранить данные из однажды прочитанного текстового файла в бинарном формате и в дальнейшем загружать эти данные из него.
Чтобы сохранить содержимое переменной x1 используем следующий вызов (указание ключевого слова file является обязательным)
Очистка рабочей области от загруженных и используемых переменных
Перед загрузкой данных, только что сохраненных в файл sol_x1.RData , сперва очистим рабочую область (удалим все загруженные переменные). Сделать это можно либо функцией rm . Приведенный вызов удалит все загруженные объекты.
Либо кликнув по кнопке Clear .
Объекты также можно удалять выборочно, указывая их названия.
Иногда при длительной работе и загрузке удалении больших объемом данных бывает полезно вызывать сборщик мусора, который принудительно очищает память от уже неиспользуемых данных.
Чтение данных в бинарном формате
Загрузим ранее сохраненный файл sol_x1.RData
Как вы могли заметить в списке загруженных переменных появилась новая с именем x1 как у ранее сохраненного data.frame.
Однако если в разных файлах сохранены объекты с одинаковым названием, то для их одновременной загрузки эти объекты необходио переименовать. Это можно во время загрузки данных, использовав следующий набор команд:
Проверим загруженный объект x1.1 на идентичность с x1
Сохранение данных в текстовом формате
Функция write.table сохраняет данные в текстовом формате. Она имеет много параметров для гибкой настройки вида сохраняемого файла.
Другие функции для работы с текстовыми файлами
Существуют различные дополнительные функции для чтения и записи текстовых файлов с определенным стилем форматирования. Подробную информацию о них можно найти в справочной системе R.
Другие способы ввода-вывода
Помимо текстовых и бинарных данных R может читать данные из различных баз данных, а также файлов MS Excel, для чего используется подключение дополнительных пакетов. В частности пакет xlsx позволяет работать с данными, сохраненными в одноименном формате.
Создание пользовательских функций
Если часто используется одна и та же последовательность команд, то целесообразнее создать функцию, которая бы их выполняла автоматически. Это существенно упрощает текст программы, делает его более модульным, читабельным и простым для внесения изменений.
Создадим простейшую функцию рассчитывающую разность двух векторов
Важно отметить, что при передаче параметров в функции, можно не использовать названия параметров только в том случае, если соблюдается порядок следования параметров. В противном случае необходимо указывать названия параметров.
Продемонстрируем области видимости переменных на примере собственных функций.
Создадим вектор x и вызовем созданную нами функцию. Результат функции это измененный вектор x , однако сам вектор x не изменился.
Таким образом все что передается в функцию попадает в локальную области видимости только этой функции как и все изменения.
Реализуем собственную функцию загрузки бинарных файлов
Ключевое слово return в завершении функции писать не обязательно. По умолчанию функция возвращает результат последней операции.
Для того чтобы сохранить созданную функцию текст функции посещается в (новый) файл R script, который можно создать вызвав меню File - New file - R script или нажав комбинацию Ctrl + Shift + N. После чего пишется текст функции и файл сохраняется с расширением “.R”.
Для загрузки функции из файла используется функция source . Но предварительно очистим содержимое рабочей области.
После чего для загрузки бинарного файла достаточно вызвать
Ранее для чтения текстового файла с дескрипторами мы использовали следующий вызов.
Если часто использовать ее для чтения файлов, то удобнее создать собственную функцию. Создадим два варианта.
Первый вариант
Троеточие используется для передачи дополнительных параметров внутрь функций.
Тогда для загрузки файлов с дескрипторами достаточно вызвать
Какие достоинства и недостатки у каждого из вариантов?
Задания
- Создать функцию, которая будет считывать текстовый файл, содержащий дескрипторы, с использованием функции fread, и возвращать data.frame.
- Прочитать с использованием функции из п.1 и сохранить в бинарном формате файл sol_x2.txt .
- Прочитать файл sol_y1.txt , конвертировать загруженные данные в именованный вектор и сохранить его в бинарном формате. Создать для этого соответствующую функцию.
- Повторить операции п.3 для файла sol_y2.txt
Манипуляции с данными
Векторы
Загрузим файл sol_y1.RData и определим среднее значение растворимости в выборке, медианное значение, максимальное и минимальное значения.
Все приведенные функции векторизированы, поэтому расчет происходит очень быстро и эффективно.
Функция summary возвращает всю вышеприведенную статистику в виде одного вектора значений.
Помимо этих есть еще множество функций рассчета различных статистических характеристик.
Data.frames
Продемонстрируем работу с data.frames на примере.
Есть два набора соединений с рассчитанными дескрипторами и их необходимо объединить в один data.frame.
Загрузим оба имеющихся файла данных:
Проверим размерность загруженных данных. Функция dim возвращает размерность данных (число строк и число столбцов), другими словами число соединений и число дескрипторов.
Поскольку число дескрипторов отличается, то выясним какие дескрипторы отсутствуют в каждом из наборов данных.
Функция setdiff возвращает элементы первого вектора, которые отсутствуют во втором
var.names1 содержит имена дескрипторов, которые присутствуют в x1 и отсутствуют в x2 . Аналогично для var.names2 .
Посмотрим сколько таких дескриптров в каждом случае
Т.е. первый набор данных содержит 923 дескриптора, которые отсутствуют вов втором наборе, а второй - 383, которые отсутствуют в первом.
Поскольку мы используем фрагментные дескрипторы, то их отсутствие фактически означает, что число дескриторов данного вида равно нулю. Следовательно мы должны добавить отсутствующие дескрипторы в каждый набор данных и приравнять все их значения нулю.
Чтобы добавить нулевые значения этим дескрипторам мы вызываем их для соответствующего data.frame и присваиваем значение 0 .
Проверям размерность полученных данных
Число колонок (дескрипторов) теперь идентично. Проверим порядок следования дескриптров в каждом наборе, используя следующую конструкцию
Выражение в скобках возвращает вектор логических значений, который содержит TRUE в случае если на одинаковых позициях находятся одинаковые значения и FALSE в противном случае. Функция all возвращает TRUE , если все значения логического вектора равны TRUE .
Проверим действительно ли имена дескрипторов в обоих data.frames совпадают и мы ничего не упустили. Используем для этого функцию %in% , которая принимает два вектора, и если значение первого вектора присутствует во втором, то для этого элемента возвращается значение TRUE . Таким образом выражение записанное ниже можно прочитать как “все ли названия колонок первого набора данных присутствуют во втором наборе”
Аналогично выполняется проверка для второго набора
Две эти проверки можно заменить одной, если предварительно отсортировать имена колонок в обоих наборах почле чего сравнить их
Теперь перед объединением строк обоих data.frames необходимо расположить колонки в одинаковом порядке. Воспользуемся для этого свойством индексов и расположим колонки в x2 в той же последовательности что и в x1
Теперь колонки расположены в одной последовательности. Проверим
Полученные data.frames теперь можно объединить в один с использованием функции rbind - объединение данных по строкам (row bind).
Аналогично когда надо объединить данные по колонкам используется функция cbind .
Загрузим и объединим значения свойства для двух наборов данных
Посмотрим на распределение значений свойства
Простейшие функции для работы с графикой
Базовый пакет R имеет в своем составе много функций для визуализации данных. Остановимся только на некоторых, которые могут быть полезны при первом знакомстве с данными.
Функция hist - строит гистограмму распределения какой-либо величины. Может помочь составить первое впечатление о нормальности распределения данных. Применим эту функцию к свойству y .
Если стандартное отображение не устраивает, то можно его изменить, например, сделав интервалы меньше.
Во всех случаях очевидно, что распределение данных отличается от нормального. Чтобы проверить это можно воспользоваться следующими двумя функциями, которые строят график зависимости между квантилями нормального распределения и квантилями исследуемого набора значений y . Чем сильнее отличие распределения от прямой, тем больше отклонение распределения от нормального.
Для более подробного знакомства с возможностями базовых функций графического отображения рекомендую ознакомиться со следующими источниками:
Семейство функций apply
apply
Семейство функций apply является более удобным аналогом цикла for .
Рассмотрим пример - необходимо найти среднее значение каждой колонки в data.frame.
Решение с использованием цикла for
Решение с использованием функции apply
Правда короче и проще? Кроме того вектор с результатами содержит названия переменных.
А вот выражение, которое вычисляет среднее значение по строкам
На самом деле для операции нахождения среднего и суммы по строкам/столбцам есть отдельные векторизированные функции rowMeans , rowSums и т.д.
Общий вид вызова функции apply
X - матрица, массив или data.frame
MARGIN - порядковый номер размерноси, к которой будет применяться функция FUN (1 для строк, 2 для колонок)
FUN - применяемая функция
Результатом будет являться вектор (если используемая функция возвращает одно значение), массив (если функция возвращает вектор значений) или список (если функция возвращает результат в виде более сложной структуры данных, например data.frame или матрица).
ВАЖНО! При применении функции apply к data.frame, data.frame неявно приводится к матрице. Матрицы как мы помним содержат данные только одного типа. Это означеат что если в data.frame 9 числовых колонок и 1 текстовая, то будет произведена конвертация в текстовую матрицу, и следовательно все действия будут производиться над текстовой матрицей.
Пример
Чуть более сложный пример - надо посчитать для каждой колонки среднее значение и извлечь из него квадратный корень. выполним это с использованием функции apply
Предложите альтернативный вариант расчета.
sapply & lapply
Помимо функции apply есть еще функции sapply и lapply , отличие которых состоит в том, что на вход они могут принимать вектор или список и возвращают вектор/матрицу ( sapply ) или список ( lapply ).
Вспомним, что data.frame является списком векторов-столбцов. Тогда предыдущий пример можно переписать как
Использование lapply вернет уже список
Возведем значения каждой колонки в степень, соответствующую номеру этой колонки - результатом будет новая матрица.
Обратите внимание, что в этом случае в качестве первого параметра передается не data.frame, а вектор индексов колонок, по которым происходит итерация.
Функция seq_along возвращает вектор индексов с первого до последнего элемента вектора/списка.
Использование функций семейства apply позволяет делать код более простым и читабельным.
Например, надо определить класс каждой колонки в data.frame
Как видим в отличие от apply фугкция sapply не производит неявной конвертации data.frame в матрицу и типы данных в колонках остаются неизменными.
Проверить совпадает ли порядок следования имен соединений в x и y .
Создать функцию, которая читала бы формат файлов дескрипторов dat/cds. Подсказка: можно использовать функцию readBin .
Создать функцию, которая будет объединять два набора фрагментных дескрипторов.
Data Frame используются для хранения табличных данных. Они представляют собой особый тип списков (lists), матрицу данных. Это – именованный список векторов одной и той же длины, в которых элементы отвечают за переменные. В отличие от матриц, таблица данных содержит элементы разных классов, т.е. допускаются столбцы с числовыми, текстовыми и логическими значениями.
Создать Data Frame
Для создания таблицы данных применяется функция data.frame()
Определение таблицы данных на основе векторов
Определим сначала два вектора, а после введем величину d, которая является таблицей данных, включающей эти два вектора:
Еще один пример по созданию таблицы данных
Пусть требуется изменить названия столбцов. Тогда
Кроме того, вывод значений 1-го столбца (переменной) осуществляется следующим образом
Изложенная процедура создания таблицы данных с изменением названий столбцов имеет аналог
Выбор числа, строк и столбцов
Для работы со списком по одной переменной (столбцом) используется знак $
[1] 5260 5470 5640 6180 6390 6515 6805 7515 7515 8230 8770
Если нужно взять определенные элементы из вектора, пользуемся записью вида
[1] 5640 6390 6805
Здесь с(…) запись, которая определяет вектор, состоящий из чисел под указанными порядковыми номерами.
Это же можно делать следующим образом
[1] 5640 6390 6805
Кроме того, применяются логические условия для выбора чисел из вектора
intake.post[intake.pre > 7000 & intake.pre <= 8000]
Индексирование с data frame происходит так
В квадратных скобках первый параметр указывает на номер строки, а второй – столбца. То же самое получаем, если вместо номера указывается наименование переменной
Если нужна конкретная строка целиком, например, 5-я, то записываем
Следует подчеркнуть, что запятая нужна.
По аналогии получаем все значения по конкретному столбцу
[1] 3910 4220 3885 5160 5645 4680 5265 5975 6790 6900 7335
Пусть необходимо вывести значения по заданным строкам и столбцам. Для этого следует выполнить
Выбор по условию
Если нужна выборка записей (строк), которые соответствуют выполнению условия по одной переменной, то команда имеет такой вид
Данную выборку можно получить несколько другим способом
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE
Шапка – head ()
Работая над большим массивом данных, часто есть потребность посмотреть несколько первых строк. В таком случае можно выбрать один из двух способов.
Конец – tail()
Чтобы посмотреть конец таблицы, введите tail() .
Сведения о таблице: количество строк и столбцов, их названия
Чтобы узнать, сколько строк и столбцов насчитывается в таблице, воспользуемся функцией dim()
Благодаря dimnames() можно увидеть названия строк и столбцов
Как видим, Data Frame имеет особый атрибут raw.names
Чтобы узнать и применять в дальнейших расчетах количество строк, вводим функцию nrow(). А количество столбцов определяется через ncol().
Полезной функцией для получения информации о таблице данных является str()
При создании таблицы можно указать, что переменная типа “Factor” является “Character”
На эксклюзивных условиях представляем для вас полный вариант статьи из журнала Хакер, посвященной разработке на R. Под катом вы узнаете, как выжать максимум скорости при работе с табличными данными в языке R.
Примечание: орфография и пунктуация автора сохранены.
К чему лишние слова? Ты же читаешь статью про скорость, поэтому давай сразу к сути! Если у тебя в проекте идет работа с большим объемом данных и на трансформацию таблиц тратится больше времени, чем хотелось, то data.table поможет решить эту проблему. Статья будет интересна тем, кто уже немного знаком с языком R, а также разработчикам, которые его активно используют, но еще не открыли для себя пакет data.table .
Все необходимое для нашей сегодняшней статьи можно проинсталлить с помощью соответствующих функций:
В последние годы язык R заслуженно набирает популярность в среде машинного обучения. Как правило, для работы с этим подразделом искусственного интеллекта необходимо загрузить данные из нескольких источников, провести с ними преобразования для получения обучающей выборки, на ее основе создать модель, а затем использовать эту модель для предсказаний.
На словах все просто, но в реальной жизни для формирования «хорошей» и устойчивой модели требуется множество попыток, большинство из которых могут быть абсолютно тупиковыми. Язык R помогает упростить процесс создания такой модели, так как это эффективный инструмент анализа табличных данных. Для работы с ними в R существует встроенный тип данных data.frame и огромное количество алгоритмов и моделей, которые его активно используют. К тому же вся мощь R заключается в возможности расширять базовую функциональность с помощью сторонних пакетов. В момент написания материала их количество в официальном репозитории достигло 8914.
Но, как говорится, нет предела совершенству. Большое количество пакетов позволяют облегчить работу с самим типом данных data.frame . Обычно их цель — упростить синтаксис для выполнения наиболее распространенных задач. Здесь нельзя не вспомнить пакет dplyr , который уже стал стандартом де-факто для работы с data.frame , так как за счет него читаемость и удобство работы с таблицами выросли в разы.
Перейдем от теории к практике и создадим data.frame DF со столбцами a , b и с .
- выбрать только столбцы a и с ,
- отфильтровать строчки, где a = 2 и с > 10,
- создать новую колонку aс , равную сумме a и с ,
- записать результат в переменную DF2 ,
базовый синтаксис на чистом data.frame будет такой:
С помощью dplyr все гораздо нагляднее:
Эти же шаги, но с комментариями:
Есть и альтернативный подход для работы с таблицами — data.table . Формально data.table — это тоже data.frame , и его можно использовать с существующими функциями и пакетами, которые зачастую ничего не знают о data.table и работают исключительно с data.frame . Этот «улучшенный» data.frame может выполнять многие типовые задачи в несколько раз быстрее своего прародителя. Возникает законный вопрос: где подвох? Этой самой «засадой» в data.table оказывается его синтаксис, который сильно отличается от оригинального. При этом если dplyr с первых же секунд использования делает код легче для понимания, то data.table превращает код в черную магию, и только годы изучения колдовских книг несколько дней практики с data.table позволят полностью понять идею нового синтаксиса и принцип упрощения кода.
Для работы с data.table необходимо подключить его пакет.
В дальнейших примерах эти вызовы будут опущены и будет считаться, что пакет уже загружен.
Так как данные очень часто загружаются из файлов CSV, то уже на этом этапе data.table может удивлять. Для того чтобы показать более измеримые оценки, возьмем какой-нибудь достаточно большой файл CSV. В качестве примера можно привести данные с одного из последних соревнований на Kaggle. Там ты найдешь тренировочный файл CSV размером в 1,27 Гбайт. Структура файла очень простая:
- row_id — идентификатор события;
- x , y — координаты;
- accuracy — точность;
- time — время;
- place_id — идентификатор организации.
Попробуем воспользоваться базовой функцией R — read.csv и измерим время, которое понадобится для загрузки этого файла (для этого обратимся к функции system.time ):
Время выполнения — 461,349 секунды. Достаточно, чтобы сходить за кофе… Даже если в будущем ты не захочешь пользоваться data.table , все равно старайся реже применять встроенные функции чтения CSV. Есть хорошая библиотека readr , где все реализовано гораздо эффективнее, чем в базовых функциях. Посмотрим ее работу на примере и подключим пакет.
Дальше воспользуемся функцией загрузки данных из CSV:
Время выполнения — 38,067 секунды — значительно быстрее предыдущего результата! Посмотрим, на что способен data.table:
Время выполнения — 20,906 секунды, что почти в два раза быстрее, чем в readr , и в двадцать раз быстрее, чем в базовом методе.
В нашем примере разница в скорости загрузки для разных методов получилась достаточно большая. Внутри каждого из используемых методов время линейно зависит от объема файла, но разница в скорости между этими методами сильно зависит от структуры файла (количества и типов столбцов). Ниже указаны тестовые замеры времени загрузки файлов.
Для файла из трех текстовых колонок видно явное преимущество fread :
Если же считываются не текстовые, а цифровые колонки, то разница между fread и read_csv менее заметна:
Если после загрузки данных из файла ты собираешься дальше работать с data.table , то fread сразу его возвращает. При других способах загрузки данных будет необходимо сделать data.table из data.frame , хотя это просто:
Большинство оптимизаций по скорости в data.table достигается за счет работы с объектами по ссылке, дополнительные копии объектов в памяти не создаются, а значит, экономится время и ресурсы.
Например, ту же задачу создать data.table из data.frame можно было бы решить одной командой на «прокачку», но надо помнить, что первоначальное значение переменной будет потеряно.
Итак, данные мы загрузили, пора с ними поработать. Будем считать, что в переменной DT уже есть загруженный data.table . Авторы пакета используют следующее обозначение основных блоков DT[i, j, by] :
- i — фильтр строк;
- j — выбор колонок или выполнение выражения над содержимым DT ;
- by — блок для группировки данных.
Вспомним самый первый пример, где мы использовали data.frame DF , и на нем протестируем различные блоки. Начнем с создания data.table из data.frame :
Блок i — фильтр строк
Это самый понятный из блоков. Он служит для фильтра строк data.table , и, если больше ничего дополнительно не требуется, остальные блоки можно не указывать.
Блок j — выбор колонок или выполнение выражения над содержимым data.table
В данном блоке выполняется обработка содержимого data.table с отфильтрованными строками. Ты можешь просто попросить вернуть нужные столбцы, указав их в списке list . Для удобства введен синоним list в виде точки (то есть list (a, b) эквивалентно .(a, b) ). Все существующие в data.table столбцы доступны как «переменные» — тебе не надо работать с ними как со строками, и можно пользоваться intellisense.
Можно также указать дополнительные колонки, которые хочешь создать, и присвоить им необходимые значения:
Если все это объединить, можно выполнить первую задачу, которую мы пробовали решать разными способами:
Выбор колонок — всего лишь часть возможностей блока j. Также там можно менять существующий data.table . Например, если мы хотим добавить новую колонку в существующем data.table , а не в новой копии (как в прошлом примере), это можно сделать с помощью специального синтаксиса := .
С помощью этого же оператора можно удалять колонки, присваивая им значение NULL .
Работа с ресурсами по ссылке здорово экономит мощности, и она гораздо быстрее, так как мы избегаем создания копии одних и тех же таблиц с разными колонками. Но надо понимать, что изменение по ссылке меняет сам объект. Если тебе нужна копия этих данных в другой переменной, то надо явно указать, что это отдельная копия, а не ссылка на тот же объект.
Может показаться, что мы поменяли только DT3 , но DT2 и DT3 — это один объект, и, обратившись к DT2 , мы увидим там новую колонку. Это касается не только удаления и создания столбцов, так как data.table использует ссылки в том числе и для сортировки. Так что вызов setorder(DT3, "a") повлияет и на DT2 .
Для создания копии можно воспользоваться функцией:
Теперь DT2 и DT3 — это разные объекты, и мы удалили столбец именно у DT3 .
by — блок для группировки данных
Этот блок группирует данные наподобие group_by из пакета dplyr или GROUP BY в языке запросов SQL. Логика обращения к data.table с группировкой следующая:
- Блок i фильтрует строки из полного data.table .
- Блок by группирует данные, отфильтрованные в блоке i, по требуемым полям.
- Для каждой группы выполняется блок j, который может либо выбирать, либо обновлять данные.
Блок заполняется следующим способом: by=list(переменные для группировки) , но, как и в блоке j, list может быть заменен на точку, то есть by=list(a, b) эквивалентно by=.(a, b) . Если необходимо группировать только по одному полю, можно опустить использование списка и написать напрямую by=a :
Самая частая ошибка тех, кто учится работать с data.table , — это применение привычных по data.frame конструкций к data.table . Это очень больное место, и на поиск ошибки можно потратить очень много времени. Если у нас в переменных DF2 ( data.frame ) и DT2 ( data.table ) находятся абсолютно одинаковые данные, то указанные вызовы вернут абсолютно разные значения:
Причина этого очень проста:
- логика data.frame следующая — DF2[1:5,1:2] означает, что надо взять первые пять строк и вернуть для них значения первых двух колонок;
- логика data.table отличается — DT2[1:5,1:2] означает, что надо взять первые пять строк и передать их в блок j. Блок j просто вернет 1 и 2 .
Если надо обратиться к data.table в формате data.frame , необходимо явно указать это с помощью дополнительного параметра:
Давай убедимся, что изучение этого синтаксиса имеет смысл. Вернемся к примеру с большим файлом CSV. В train_DF загружен data.frame , а в train_DT , соответственно, data.table .
В используемом примере place_id является целым числом большой длины ( integer64 ), но об этом «догадался» только fread . Остальные методы загрузили это поле как число с плавающей запятой, и нам надо будет явно провести преобразование поля place_id внутри train_DF , чтобы сравнить скорости.
Допустим, перед нами поставлена задача посчитать количество упоминаний каждого place_id в данных.
В dplyr с обычным data.frame это заняло 13,751 секунды:
При этом data.table делает то же самое за 2,578 секунды:
Усложним задачу — для всех place_id посчитаем количество, медиану по x и y , а затем отсортируем по количеству в обратном порядке. data.frame c dplyr справляются с этим за 27,386 секунды:
data.table же справился намного быстрее — 12,414 секунды:
Тестовые замеры времени выполнения простой группировки данных с помощью dplyr и data.table :
Это все лишь поверхностное описание функциональности data.table , но его достаточно, чтобы начать пользоваться этим пакетом. Сейчас развивается пакет dtplyr , который позиционируется как реализация dplyr для data.table , но пока он еще очень молод (версия 0.0.1). В любом случае понимание особенностей работы data.table необходимо до того, чтобы пользоваться дополнительными «обертками».
Станислав Чистяков — эксперт по облачным технологиям и машинному обучению.
Очень советую почитать статьи, входящие в состав пакета:
Тема языка R не впервые поднимается в нашем журнале. Подкинем тебе еще пару линков на статьи по теме:
Во-первых, давайте получим некоторые данные. Пакет MASS содержит данные о 93 автомобилях, поступивших в продажу в США в 1993 году. Они хранятся в объекте Cars93 и включают 27 признаков для каждого автомобиля, некоторые из которых являются категориальными. Итак, давайте загрузим пакет MASS и посмотрим на тип транспортных средств, включенных в cars93:
У нас там 6 типов автомобилей. Функция table сообщает, сколько у нас их каждого типа:
Отлично, мы увидели, что наш набор данных содержит одинаковое количество автомобилей из США и не из США, и что наиболее распространенными типами являются Midsize и Small. Однако, может быть, США и неамериканцы различаются по типам?
Давайте посмотрим на типы автомобилей с точки зрения их происхождения. Мы можем снова использовать table, но теперь с двумя аргументами. Первый станет переменной строки, а второй станет переменной столбца:
Теперь мы увидели то, что все знают и так: американцы любят большие машины! В таблице выше показано совместное распределение двух категориальных переменных (Type и Origin). Такие таблицы называются таблицами сопряженности.
Как получить маржинальную форму таблицы сопряженности
Функции rowSums и colSums действительно говорят сами за себя
Как получить проценты из таблицы сопряженности
Преобразование в проценты - это просто умножение на 100:
Обратите внимание, что это совместное распределение вероятностей, из которого мы видим, например, что около 7,5% автомобилей являются небольшими и имеют американское происхождение.
Чаще всего нас интересует распределение одной переменной внутри групп, созданных другой. Здесь интересным представляется распределение типов автомобилей среди американских и (отдельно) неамериканских автомобилей. Чтобы получить это, мы используем аргумент margin для функции prop.table. Он сообщает, где в строках (margin = 1) или в столбцах (margin = 2) переменная группировки:
Теперь мы можем легко увидеть, что маленькие автомобили встречаются за пределами США в два раза чаще, чем в США.
Также обратите внимание, что проценты составляют до 100 в столбцах, тогда как в объединенной таблице распределения (таблица без аргумента margin) 100 представляла собой сумму всей таблицы.
Наиболее распространенный вопрос, который возникает в таблицах сопряженности, заключается в том, являются ли переменные строк и столбцов независимыми. Самый простой способ ответить на него - запустить тест хи-квадрат. Он подробно описан в этом руководстве. Давайте проверим, являются ли Type и Origin независимыми:
Точный критерий Фишера является альтернативой критерию хи-квадрат, используемой в основном, когда аппроксимация хи-квадрат не является удовлетворительной. Давайте запустим его:
Результаты очень похожи на результаты из хи-квадрат, но это не всегда так. Одним из основных недостатков точного теста Фишера является то, что для больших таблиц (или больших выборок) он становится неэффективным в вычислительном отношении.
Другой альтернативой является так называемый G-тест. Его статистика также приблизительно распределена по хи-квадрат, но для небольших выборок это приближение лучше, чем при использовании теста хи-квадрат. Для G-теста мы можем использовать функцию GTest из пакета DescTools. Результаты снова очень похожи на два предыдущих теста: Type и Origin не являются независимыми.
В таблицах сопряженности 2x2 критерий хи-квадрат может быть улучшен с помощью поправки непрерывности Йейтса. Она просто вычитает 0,5 из каждого члена | Наблюдаемый - Ожидаемый | в статистике хи-квадрат. Снова обратитесь к этому руководству, если вы не понимаете, о чем идет речь. Более того, R применяет поправку Йейтса автоматически, когда это необходимо. Давайте посмотрим на наличие версий с механической коробкой передач для автомобилей США и неамериканских:
Поправка Йейтса была применена автоматически, и R сказал нам об этом.
Давайте посмотрим на Man.trans.avail, Origin и Type одновременно. table разбивает набор данных в соответствии с переменной, представленной как третья:
Из приведенных выше результатов должно быть ясно, что зависимость между Origin и Man.trans.avail отличается от Type. Например, для небольших и спортивных автомобилей ассоциация отсутствует: каждый американский, а также любой неамериканский маленький или спортивный автомобиль выпускается с ручной коробкой передач. С другой стороны, большинство автомобилей среднего размера в США не имеют такой версии, в то время как большинство неамериканских автомобилей этого типа имеют. Чтобы учесть возможные различия, можно использовать критерий Кохрана-Мантеля-Хензеля:
Третий аргумент, переданный mantelhaen.test, определяет страты. Сравните приведенные выше результаты с результатами без стратификации (пример поправки Йейтса выше). Ассоциация все еще присутствует, но доказательства для этого гораздо слабее.
Как только мы обнаружили некоторые связи между переменными, пришло время измерить их силу. Существует множество различных типов возможных мер. Многие из них описаны здесь. Сейчас я остановлюсь на двух наиболее широко используемых.
N - общий итог таблицы сопряженности (сумма всех ее ячеек),
V [0; 1]. Чем больше V, тем сильнее связь между переменными. V = 0 можно интерпретировать как независимость (поскольку V = 0 тогда и только тогда, когда χ2 = 0). Основным недостатком V является отсутствие точной интерпретации. Является ли V = 0,6 сильной, умеренной или слабой ассоциацией?
Функция CramerV от DescTools может рассчитать это для нас:
Еще раз: это сильная, умеренная или слабая ассоциация?
они выражают долю вариаций, объясняемых независимой переменной.
Это лучше всего объяснить на примере. Давайте посмотрим на Type и Origin, последняя будет независимой:
Мода столбца US - 11, поэтому L1 = 7 + 10 + 7 + 8 + 5 = 37. Мода столбца non-US - 14, поэтому L2 = 9 + 0 + 12 + 6 + 4 = 31.
Вместо этого мы можем использовать функцию Lambda из пакета DescTools:
Параметр direction определяет, где (в строке или в столбце) находится зависимая переменная.
Origin объясняет только около 4% изменений в Type. Обратите внимание на формулу, что лямбда определяет вариацию как дихотомию между принадлежностью и не принадлежностью к самой большой группе.
Стоит отметить, что лямбда равна нулю, когда модальная категория каждого столбца одинакова. Посмотрите на эту таблицу:
Модальная категория одинакова для каждого столбца (это вторая строка). Таким образом, лямбда должна быть нулевой, несмотря на значительную и видимую связь:
Комментариев нет:
Подпишитесь на RSS
Перевод. Оригинал здесь. Если вы новичек в Linux и ранее использовали iTunes для управления своим iPod/iPhone/iPad, то скорее всего буд.
uTorrent - это легкий и эффективный торрент-клиент для Linux, Windows OS и Mac OS. Установка uTorrent в Linux отличается тем, что здесь uT.
Вы можете запускать скрипты на python в Linux непосредственно из терминала. Знать, как это делается, полезно как программистам, так и пол.
Как вы наверное знаете, Safari является браузером по умолчанию в Mac OS X и iPhone OS. Вышло уже несколько релизов и для Windows, но версии .
Способ сброса пароля root в CentOS 7 кардинально отличается от такового в Centos 6. 1. В загрузочном меню нажмите "е" - реда.
Читайте также: