r loops dataframe matching closest

R-Asigna valor de columna en función de la coincidencia más cercana en el segundo marco de datos



loops dataframe (2)

Tengo dos marcos de datos, logger y df (los tiempos son numéricos):

logger <- data.frame( time = c(1280248354:1280248413), temp = runif(60,min=18,max=24.5) ) df <- data.frame( obs = c(1:10), time = runif(10,min=1280248354,max=1280248413), temp = NA )

Me gustaría buscar logger $ time para la coincidencia más cercana a cada fila en df $ time, y asignar el logger $ temp asociado a df $ temp. Hasta ahora, he tenido éxito usando el siguiente ciclo:

for (i in 1:length(df$time)){ closestto<-which.min(abs((logger$time) - (df$time[i]))) df$temp[i]<-logger$temp[closestto] }

Sin embargo, ahora tengo grandes marcos de datos (el registrador tiene 13.620 filas y df tiene 266138) y los tiempos de procesamiento son largos. He leído que los bucles no son la forma más eficiente de hacer las cosas, pero no estoy familiarizado con las alternativas. ¿Hay una manera más rápida de hacer esto?


Puede usar la biblioteca data.table . Esto también ayudará a ser más eficiente con un gran tamaño de datos.

library(data.table) logger <- data.frame( time = c(1280248354:1280248413), temp = runif(60,min=18,max=24.5) ) df <- data.frame( obs = c(1:10), time = runif(10,min=1280248354,max=1280248413) ) logger <- data.table(logger) df <- data.table(df) setkey(df,time) setkey(logger,time) df2 <- logger[df, roll = "nearest"]

Salida -

> df2 time temp obs 1: 1280248356 22.81437 7 2: 1280248360 24.08711 10 3: 1280248366 22.31738 2 4: 1280248367 18.61222 5 5: 1280248388 19.46300 4 6: 1280248393 18.26535 6 7: 1280248400 20.61901 9 8: 1280248402 21.92584 1 9: 1280248410 19.36526 8 10: 1280248410 19.36526 3


data.table para esto. Hace que sea súper fácil y súper rápido unir las keys . Incluso hay un argumento roll = "nearest" realmente útil para exactamente el comportamiento que está buscando (excepto en los datos de su ejemplo, no es necesario porque todos los times de df aparecen en el logger ). En el siguiente ejemplo, renombré df$time a df$time1 para dejar en claro qué columna pertenece a qué tabla ...

# Load package require( data.table ) # Make data.frames into data.tables with a key column ldt <- data.table( logger , key = "time" ) dt <- data.table( df , key = "time1" ) # Join based on the key column of the two tables (time & time1) # roll = "nearest" gives the desired behaviour # list( obs , time1 , temp ) gives the columns you want to return from dt ldt[ dt , list( obs , time1 , temp ) , roll = "nearest" ] # time obs time1 temp # 1: 1280248361 8 1280248361 18.07644 # 2: 1280248366 4 1280248366 21.88957 # 3: 1280248370 3 1280248370 19.09015 # 4: 1280248376 5 1280248376 22.39770 # 5: 1280248381 6 1280248381 24.12758 # 6: 1280248383 10 1280248383 22.70919 # 7: 1280248385 1 1280248385 18.78183 # 8: 1280248389 2 1280248389 18.17874 # 9: 1280248393 9 1280248393 18.03098 #10: 1280248403 7 1280248403 22.74372