Ответ 1
Data IO была одной из особенностей, которую я изучил, прежде чем я посвятил себя обучению R. Для улучшения или хуже, вот мои наблюдения и решения/паллиативы по этим вопросам:
1. Что R не обрабатывает большие данные ( > 2 ГБ?) Мне это неверно. По умолчанию общие функции ввода данных загружают ваши данные в ОЗУ. Не быть glib, но для меня это особенность, а не ошибка - в любое время мои данные будут соответствовать моей доступной ОЗУ, где я хочу. Аналогично, одной из самых популярных функций SQLite является опция in-memory - у пользователя есть простой способ загрузки всего дБ в ОЗУ. Если ваши данные не будут вписываться в память, тогда R делает его удивительно простым в использовании, подключаясь к общим системам РСУБД (RODBC, RSQLite, RMySQL и т.д.), Используя опции без излишеств, такие как пакет filehash, и через системы, которые используют текущую технологию/практику (например, я могу рекомендовать ff). Другими словами, разработчики R выбрали разумный (и, вероятно, оптимальный) по умолчанию, из которого очень легко отказаться.
2. Производительность read.table (read.csv, read.delim и др.), Наиболее распространенное средство для получения данных в R, может быть улучшена 5 раз (и часто намного больше в моем опыте), просто выбрав из нескольких аргументов read.table по умолчанию - те, которые оказывают наибольшее влияние на производительность, упоминаются в справке R (? read.table). Вкратце, разработчики R сообщают нам, что если вы предоставите значения для параметров colClasses, 'nrows', 'sep' и 'comment.char' (в частности, перейдите в '', если вы знаете, что ваш файл начинается с заголовков или данные в строке 1), вы увидите значительное увеличение производительности. Я нашел это, чтобы быть правдой.
Вот фрагменты, которые я использую для этих параметров:
Чтобы получить количество строк в вашем файле данных (поставьте этот фрагмент в качестве аргумента для параметра "nrows" в вашем вызове read.table):
as.numeric((gsub("[^0-9]+", "", system(paste("wc -l ", file_name, sep=""), intern=T))))
Чтобы получить классы для каждого столбца:
function(fname){sapply(read.table(fname, header=T, nrows=5), class)}
Примечание. Вы не можете передать этот фрагмент в качестве аргумента, вы должны сначала его вызвать, а затем передать возвращаемое значение - другими словами, вызвать функцию, связать возвращаемое значение с переменной, а затем перейдите в переменную как значение к параметру "colClasses" в вашем вызове read.table:
3. Использование Scan. С небольшим количеством проблем вы можете сделать лучше (оптимизируя "read.table" ), используя "scan" вместо "read.table" ( "read.table" на самом деле просто обертка вокруг "scan" ). Еще раз, это очень легко сделать. Я использую "сканирование" для ввода каждого столбца отдельно, а затем создаю свой файл data.frame внутри R, т.е. Df = data.frame(cbind (col1, col2,....)).
4. Используйте R Containers для сохранения на месте вместо обычных форматов файлов (например, "txt", "csv" ). R native data. '.RData' - это двоичный формат, который немного меньше сжатого (.gz ') файла данных txt. Вы создаете их, используя сохранить (,). Вы загрузите его обратно в пространство имен R с помощью load(). Разница во времени загрузки по сравнению с "read.table" является драматической. Например, с файлом размером 25 МБ (несжатый размер)
system.time(read.table("tdata01.txt.gz", sep=","))
=> user system elapsed
6.173 0.245 **6.450**
system.time(load("tdata01.RData"))
=> user system elapsed
0.912 0.006 **0.912**
5. Обращая внимание на типы данных, вы часто можете повысить производительность и уменьшить объем памяти. Этот момент, вероятно, более полезен для получения данных из R. Ключевым моментом здесь является то, что по умолчанию числа в R-выражениях интерпретируются как плавающая точка с двойной точностью, например, > typeof (5) возвращает double. " Сравните размер объекта массива разумного размера, и вы можете увидеть его значение (используйте object.size()). Так что принуждение к целому числу, когда вы можете.
Наконец, семейство функций "apply" (среди прочих) не является "скрытыми петлями" или оберткими цикла. Они представляют собой петли, реализованные в C - большие различия в производительности. [edit: AWB правильно указал, что в то время как "sapply", "tapply" и "mapply" реализованы в C, "apply" - это просто оболочка.