R производительность с изменением формы данных - PullRequest
10 голосов
/ 07 декабря 2009

Я пытаюсь изменить форму фрейма данных в R, и, похоже, возникают проблемы с использованием рекомендованных способов сделать это. Фрейм данных имеет следующую структуру:

ID                     DATE1             DATE2            VALTYPE        VALUE
'abcd1233'         2009-11-12        2009-12-23           'TYPE1'        123.45
...

VALTYPE является строкой и является фактором только с двумя значениями (скажем, TYPE1 и TYPE2). Мне нужно преобразовать его в следующий фрейм данных («широкая» транспонирование) на основе общих идентификаторов и дат:

ID                     DATE1             DATE2            VALUE.TYPE1  VALUE.TYPE2
'abcd1233'             2009-11-12        2009-12-23       123.45           NA
...

Во фрейме данных содержится более 4 500 000 наблюдений (хотя около 70% VALUE с NA). Машина представляет собой рабочую станцию ​​Linux на базе Intel с 4 ГБ ОЗУ. Загрузка данных (из сжатого файла Rdata) в новый процесс R увеличивает их до 250 МБ, что явно оставляет много места для изменения формы.

Это мой опыт до сих пор:

  • Использование ванили reshape() метод:

    tbl2 <- изменить форму (tbl, direction = "wide", idvar = c ("ID", "DATE1", "DATE2"), timevar = "VALTYPE"); </p>

РЕЗУЛЬТАТ: Error: cannot allocate vector of size 4.8 Gb

  • Использование cast() метода пакета reshape:

    tbl2 <- приведение (tbl, ID + DATE1 + DATE2 ~ VALTYPE); </p>

РЕЗУЛЬТАТ: Процесс R потребляет всю оперативную память без конца. В конечном итоге пришлось убить процесс.

  • Использование by() и merge():

    sp <- by (tbl [c (1,2,3,5)], tbl $ VALTYPE, функция (x) x); tbl <- объединить (sp [["TYPE1"]], sp [["TYPE2"]], by = c ("ID", "DATE1", "DATE2"), все = ИСТИНА, сортировка = ИСТИНА); </p>

РЕЗУЛЬТАТ: работает нормально, хотя это не очень элегантно и надежно (то есть он сломается, если будет добавлено больше типов).

Чтобы добавить оскорбление ране, рассматриваемая операция может быть тривиально достигнута приблизительно в 3 строках AWK или Perl (и почти без использования ОЗУ). Поэтому возникает вопрос: как лучше выполнить эту операцию в R, используя рекомендованные методы, не используя всю доступную оперативную память?

Ответы [ 3 ]

1 голос
/ 08 декабря 2009

Как насчет того, чтобы делать это не в стиле R? Я предполагаю, что у вас есть строки TYPE1 и TYPE2 для каждого значения ID, DATE1, DATE2? Затем отсортируйте кадр данных по этим переменным и напишите большой цикл for. Вы можете многократно выполнять операции rbind () для построения таблицы, или вы можете попытаться предварительно выделить таблицу (возможно) и просто назначить слоты VALUE.TYPE1 и VALUE.TYPE2 с помощью [<-, что должно делать присваивание в место. </p>

(Обратите внимание, что если вы используете rbind (), я считаю, что это неэффективно, если у вас есть какие-либо факторные переменные, поэтому убедитесь, что все это символ!)

1 голос
/ 08 декабря 2009

Может быть, вы могли бы использовать функцию cat ()?

1 голос
/ 07 декабря 2009

Полезный трюк - объединить переменные id в символьный вектор и затем изменить форму.

tbl$NEWID <- with(tbl, paste(ID, DATE1, DATE2, sep=";"))
tbl2 <- recast(tbl2, NEWID ~ VALTYPE, measure.var="VALUE")

Это примерно на 40% быстрее в задаче аналогичного размера в моем MacBook Intel Core2 Duo 2.2 ГГц.

...