R с изменением данных
Я пытаюсь изменить кадр данных в R, и, похоже, у него проблемы с использованием рекомендуемых способов. Кадр данных имеет следующую структуру:
ID DATE1 DATE2 VALTYPE VALUE
'abcd1233' 2009-11-12 2009-12-23 'TYPE1' 123.45
...
VALTYPE
является строкой и является фактором с двумя значениями (скажем TYPE1
и TYPE2
). Мне нужно преобразовать его в следующий фрейм данных ( "широкий" транспонирование) на основе общих идентификаторов и DATE:
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 < - reshape (tbl, direction = "wide", idvar = c ( "ID", "DATE1", "DATE2" ), timevar = "VALTYPE" );
РЕЗУЛЬТАТ: Error: cannot allocate vector of size 4.8 Gb
РЕЗУЛЬТАТ: Процесс R потребляет всю ОЗУ без конца. Пришлось убить процесс в конце концов.
-
Использование by()
и merge()
:
sp < - by (tbl [c (1,2,3,5)], tbl $VALTYPE, функция (x) x);
tbl <-merge (sp [[ "TYPE1" ]], sp [[ "TYPE2" ]], by = c ( "ID", "DATE1", "DATE2" ), all = TRUE, sort = TRUE);
РЕЗУЛЬТАТ: работает отлично, хотя это не очень элегантно и надежно (т.е. оно будет ломаться, если добавлено больше типов).
Чтобы добавить оскорбление к травме, рассматриваемая операция может быть достигнута тривиально примерно в 3 строках AWK или Perl (и с едва ли используемой ОЗУ). Итак, вопрос в том, что лучший способ выполнить эту операцию в R с помощью рекомендуемых методов без использования всей доступной ОЗУ?
Ответы
Ответ 1
Полезным трюком является объединение переменных id в вектор символов, а затем изменение формы.
tbl$NEWID <- with(tbl, paste(ID, DATE1, DATE2, sep=";"))
tbl2 <- recast(tbl2, NEWID ~ VALTYPE, measure.var="VALUE")
Это примерно на 40% быстрее в проблеме аналогичного размера в моей версии intel core2 duo 2.2ghz macbook.
Ответ 2
Как сделать это не-R-образным образом? Я предполагаю, что у вас есть строка TYPE1 и TYPE2 для каждого значения ID, DATE1, DATE2? Затем сортируйте dataframe по этим переменным и напишите большой цикл for. Вы можете многократно выполнять операции rbind() для построения таблицы, или вы можете попытаться заранее выделить таблицу (возможно) и просто назначить слоты VALUE.TYPE1 и VALUE.TYPE2 с помощью [< -, которые должны выполнять назначение в -место.
(Обратите внимание, что если вы используете rbind(), я считаю, что он неэффективен, если у вас есть какие-либо фактор-переменные, поэтому убедитесь, что все вместо символа!)
Ответ 3
Может быть, вы могли бы использовать функцию cat()?