ffbase: объединить столбцы X и Y и ближайший столбец Z

Я хотел бы выполнить следующее, используя ffdf: Объединить столбцы X и Y и ближайшее время, а затем объединить закрывающий столбец B. Однако процедура, которую я знаю в меньших выборках, включает использование внешних слияний ( как показано ниже). Как можно обойти это для большой выборки, которая не поместится в памяти (и, вероятно, не будет работать с sqldf), используя ffbase? Если это невозможно, какая библиотека для этого лучше всего?

В качестве воспроизводимого примера, как показано ниже:

set.seed(1)
df.ff <- as.ffdf(cbind(expand.grid(x = 1:3, y = 1:5), time = round(runif(15) * 30)))

to.merge.ff <- as.ffdf(data.frame(x = c(2, 2, 2, 3, 2), y = c(1, 1, 1, 5, 4), time = c(17, 12, 11.6, 22.5, 2), val = letters[1:5], stringsAsFactors = F))

Я позаимствовал следующий пример из @ChinmayPatil, чтобы выделить аналогичную процедуру, которой я хотел бы следовать: (R - объединить фреймы данных при сопоставлении A, B и * ближайшего * C?):

require(data.table)
set.seed(1)
df <- setDT(cbind(expand.grid(x = 1:3, y = 1:5), time = round(runif(15) * 30)))

to.merge <- setDT(data.frame(x = c(2, 2, 2, 3, 2), y = c(1, 1, 1, 5, 4), time = c(17, 12, 11.6, 22.5, 2), val = letters[1:5], stringsAsFactors = F))

## First do a left outer merge
A <- merge(to.merge,df, by = c('x','y'), all.x = T )

## Then calculate a diff row as such
A$diff <- abs(A$time.x - A$time.y)

##then take the minimum distance
A[ , .I[which.min(diff)] , by = c('x', 'y' ) ]

person dleal    schedule 24.01.2017    source источник


Ответы (1)


Учитывая, что у моего вопроса так мало просмотров и нет ответов, я опишу подход, который я придумал для решения этой проблемы, в надежде, что кто-то сочтет его полезным (или даже для меня в качестве напоминания на будущее):

Для меня наиболее сложным аспектом выполнения этого сопоставления в одном столбце, а затем ближайшего совпадения в другом столбце является то, что я все время думал, что необходимо выполнить внешнее соединение (как описано в сообщении). Решение довольно простое, используя data.table и ffdfdply. В целях иллюстрации предположим, что есть один большой объект ffdf и одна обычная таблица data.table, которая умещается в памяти:

### Large ffdf object    
A <- as.ffdf(data.table( dates.A = seq.Date(as.Date('2008-01-01'),as.Date('2008-01-31'), by = '3 days'), 
                     letters.A = LETTERS[1:4] , value.A = runif(4) ))

### Small data.table that fits in memory
B <- data.table( date.B = seq.Date(as.Date('2008-01-01'),as.Date('2008-01-05'), by = 'days'), 
                 letters.B = LETTERS[1:4] , value.B = runif(4) )

Затем вы можете просто определить функцию, которая выполняет слияние, используя data.table и roll = 'near':

merge.ff <- function(x){
setDT(x)
x[, ':=' (dates.merge = dates.A, letters.merge = letters.A)]
B[, ':=' (dates.merge = date.B, letters.merge = letters.B)]
setkeyv(x, c('letters.merge','dates.merge'))
setkeyv(B, c('letters.merge','dates.merge'))

as.data.frame(B[x, roll = 'nearest'])
}

и примените его к A:

result <- ffdfdply( A, split = A$dates.A, FUN = merge.ff)

ключ просто использовал метод roll в data.table и передавал его в ffdfdply. Это казалось довольно эффективным.

person dleal    schedule 25.01.2017