Эффективное комбинирование и работа с большими фреймами данных

У меня есть 2 относительно больших фрейма данных в R. Я пытаюсь максимально эффективно объединить/найти все комбинации. Результирующий df оказывается огромным (длина dim(myDF1)[1]*dim(myDF2)[1]), поэтому я пытаюсь реализовать решение, используя ff. Я также открыт для использования других решений, таких как пакет bigmemory, для решения этих проблем с памятью. У меня практически нет опыта работы ни с одним из этих пакетов.

Рабочий пример — предположим, что я работаю с некоторым фреймом данных, похожим на USArrests:

library('ff')
library('ffbase')


myNames <- USArrests

myNames$States <- rownames(myNames)
rownames(myNames) <- NULL

Теперь я создам 2 фрейма данных, которые представляют некоторые конкретные наборы наблюдений из myNames. Позже я попытаюсь ссылаться на них по именам строк.

myDF1 <- as.ffdf(as.data.frame(matrix(as.integer(rownames(myNames))[floor(runif(3*1e5, 1, 50))], ncol = 3)))
myDF2 <- as.ffdf(as.data.frame(matrix(as.integer(rownames(myNames))[floor(runif(2*1e5, 1, 50))], ncol = 2)))


# unique combos:
myDF1 <- unique(myDF1)
myDF2 <- unique(myDF2)

Например, мой первый набор состояний в myDF1 — это myNames[unlist(myDF1[1, ]), ]. Затем я найду все комбинации myDF1 и myDF2, используя ikey :

# create keys:
myDF1$key <- ikey(myDF1)
myDF2$key <- ikey(myDF2)

startTime <- Sys.time()


# Create some huge vectors:
myVector1 <- ffrep.int(myDF1$key, dim(myDF2)[1])
myVector2 <- ffrep.int(myDF2$key, dim(myDF1)[1])


# This takes about 25 seconds on my machine:
print(Sys.time() - startTime)


# Sort one DF (to later combine with the other):
myVector2  <- ffsorted(myVector2)

# Sorting takes an additional 2.5 minutes:
print(Sys.time() - startTime)

1) Есть ли более быстрый способ отсортировать это?

# finally, find all combinations:
myDF <- as.ffdf(myVector1, myVector2)

# Very fast:
print(Sys.time() - startTime)

2) Есть ли альтернатива такому типу комбинации (без использования оперативной памяти)?

Наконец, я хотел бы иметь возможность ссылаться на любые исходные данные по строке/столбцу. В частности, я хотел бы получить разные типы rowSums. Например:

# Here are the row numbers (from myNames) for the top 6 sets of States:
this <- cbind(myDF1[myDF[1:6,1], -4], myDF2[myDF[1:6,2], -3])
this

# Then, the original data for the first set of States is:
myNames[unlist(this[1,]),]

# Suppose I want to get the sum of the Urban Population for every row, such as the first:
sum(myNames[unlist(this[1,]),]$UrbanPop)

3) В конечном счете, мне нужен вектор с указанным выше rowSum, чтобы я мог выполнить какое-то подмножество на myDF. Любые советы о том, как наиболее эффективно выполнить это?

Спасибо!


person ch-pub    schedule 11.09.2015    source источник


Ответы (1)


Мне довольно неясно, что вы собираетесь делать с rowSum и вашим 3) элементом, но если вам нужна эффективная и удобная для оперативной памяти комбинация двух векторов ff, чтобы получить все комбинации, вы можете использовать expand.ffgrid из ffbase. Следующее сгенерирует ваш ffdf с размерами 160 миллионов строк x 2 столбца за несколько секунд.

require(ffbase)
x <- expand.ffgrid(myDF1$key, myDF2$key)
person Community    schedule 14.09.2015
comment
expand.ffgrid хорошо подходит для того, что я пытаюсь сделать. Что я имею в виду в своем третьем замечании: какой тогда самый эффективный способ ссылаться на исходные наборы данных? Например, изначально мои df были размерами Nx2 и Mx3. Затем я добавил ключи, чтобы они стали размерами Nx3 и Mx4. Ваше решение x <- expand.ffgrid(myDF1$key, myDF2$key) дает мне (N * M) x 2 ffdf. Как мне тогда наиболее эффективно расширить это до размера (N * M) x (3 + 4) ffdf? То есть, используя комбинированные ключи в вашем объекте x, я хочу сослаться/расширить исходные данные. - person ch-pub; 22.09.2015
comment
объедините другие данные в расширенной сетке (NxM), используя слияние. См. ?merge.ffdf пакета ffbase. - person ; 30.09.2015