Мой оригинал data.table
состоит из трех столбцов.
site
, observation_number
и id
.
Например, вот все наблюдения для id = z
|site|observation_number|id
|a | 1| z
|b | 2| z
|c | 3| z
Это означает, что идентификатор z
изменился с a
до b
до c
.
Не существует фиксированного количества сайтов на один идентификатор.
Iхотите преобразовать данные в список краев, как это
|from |to||id|
|a | b| z |
|b | c| z |
фиктивные данные
sox <- data.table(site = c('a','b','c','a','c','c','a','d','e'),
obsnum =c(1,2,3,1,2,1,2,3,4),
id =c('z','z','z','y','y','k','k','k','k'))
То, как я сейчас это делаю, выглядит запутанным и очень медленным (у sox 1,5 миллионастрок и dt_out имеет около 7,5 млн. строк). Я в основном использую цикл for observation_number
, чтобы разбить данные на порции, где каждый идентификатор присутствует только один раз (то есть - только одна поездка в / из). Затем я преобразую данные и объединяю все фрагменты в новый data.table.
dt_out <- data.table()
maksimum = sox[,max(observation_number)]
for (i in 1:maksimum-1) {
i=1
mini = i
maxi = i+1
sox_t <- sox[observation_number ==maxi | observation_number ==mini, ]
temp_dt <- dcast(sox_t[id %in% sox_t[, .N, by = id][N>=2]$id,
.SD[, list(site, observation_number, a=rep(c('from', 'to')))] ,by=id],
id='id', value.var='site', formula=id~a)
dt_out <- rbind(dt_out, temp_dt)
i=max
}
Я надеюсь, что кто-то может помочь мне оптимизировать это, и желательно создать функцию, в которую я могу ввести data.table,идентификатор сайта, идентификатор номера наблюдения и идентификатор. По какой-то причине я не могу создать функцию независимо от того, что работает.
ОБНОВЛЕНИЕ
Использование системного времени (и системного времени несколько раз):
User - System - Elapsed
make_edgelist (data.table): 5.38 0.00 5.38
Data.table. with shift: 13.96 0.06 14.08
dplyr, with arrange: 6.06 0.36 6.44
псmake_edgelist был обновлен, чтобы упорядочить data.table
make_edgelist <- function(DT, site_var = "site", id_var = "id", obsnum_var = "rn1") {
DT[order(get(obsnum_var)),
list(from = get(site_var)[-.N], to = get(site_var)[-1]), by = id_var]
}
Я был удивлен, что dplyr (с lead
) был почти так же быстр, как make_edgelist и намного быстрее, чем data.table с shift
. Я предполагаю, что это означает, что dplyr будет на самом деле быстрее с более сложным лидерством / лагами / смещением.
Также я нахожу это озадачивающим - но не знаю достаточно, чтобы знать, имеет ли это какое-то значение, что dplyr использовал больше 'системное время, чем любое из двух решений data.table.
Входные данные: 1,5 миллиона строк. Результат: 0,6 млн. Строк.