Deseo de combinación de dos conjuntos de datos con ‘fecha y hora’ columnas que están presentes en ambos (POSIXct formato: dd/mm/aaaa hh:mm). A continuación es un ejemplo de los datos de los dos conjuntos de datos:

# Dataset 1 (dts1)

           datetime   count   period   
1  30/03/2011 02:32      27      561
2  30/03/2011 02:42       3      600
3  30/03/2011 02:52       0      574
4  30/03/2011 03:02       1      550
5  30/03/2011 03:12      15      600
6  30/03/2011 03:22       0      597

# Dateset 2 (dts2)

   datetime         dist car   satd      alt
1 30/03/2011 01:59  23.9   1      3     1.76       
2 30/03/2011 02:58  14.7   1      7     6.36       
3 30/03/2011 03:55  10.4   2      9    -0.34      
4 30/03/2011 04:53  35.4   1      3     3.55      
5 30/03/2011 05:52  56.1   1      7    -0.91       
6 30/03/2011 06:48  12.3   1      4     6.58      
7 30/03/2011 07:48  10.7   1      5     4.18      

Si se trataba de un simple caso de fusión de filas coincidentes de las dos imágenes a continuación, básica merge(data1, data2, by="datetime") o rbind() función podría ser utilizado.

Sin embargo, mi problema es más complicado, como el intervalos de tiempo en los dos conjuntos de datos no son iguales. Dataset 1 contiene datos en precisa intervalos de 10 minutos (cada fila contiene información sobre los 10 minutos que termina en la fecha especificada/hora), mientras que dataset 2 contiene datos en aproximado intervalos de 1 hora (cada fila incorpora información de la 1-bloque de horas que termina en la fecha especificada/tiempo).

Para hacer las cosas aún más difícil, hay un tiempo desajuste entre los tiempos de inicio de las filas de los dos conjuntos de datos (es decir,dts1: 01/03/2013 10:00:00, dts2: 01/03/2012 09:58:12). dts2 intervalos también varían a lo largo del conjunto de datos (± unos minutos de cada lado de 1 hora). Quiero vincular cada 10 minutos en la fila de datos en el conjunto de datos 1 con el bloque de horas que encaja dentro del conjunto de datos 2 (junto con todos los valores de la columna de dts2). Habrá algunas filas que podrían encajar en 2 diferentes bloques de horas (es decir, 30/03/2011 03:02), pero sólo tengo estas filas para ser vinculado a uno de los bloques de horas.

Me gustaría terminar con algo como esto:

        datetime_dts1 count period     datetime2_dts2  dist  car satd      alt  
1    30/03/2011 02:32    27    561   30/03/2011 02:58  14.7   1     7     6.36      
2    30/03/2011 02:42     3    600   30/03/2011 02:58  14.7   1     7     6.36
3    30/03/2011 02:52     0    574   30/03/2011 02:58  14.7   1     7     6.36
4    30/03/2011 03:02     1    550   30/03/2011 02:58  14.7   1     7     6.36
5    30/03/2011 03:12    15    600   30/03/2011 03:55  10.4   2     9    -0.34
6    30/03/2011 03:22     0    597   30/03/2011 03:55  10.4   2     9    -0.34

He buscado una respuesta a este problema, pero no han sido capaces de solucionarlo y mi R habilidades que no se ha avanzado. Si alguien me pudiera dar una dirección o proporcionar una solución, yo estaría muy agradecido.

  • podrías dput de salida? es un dolor para obtener los datos
  • Yo no podía seguir su texto largo, pero no podía usted a la vuelta de los tiempos y de combinación basada en el redondeado de los tiempos?
  • 5ª fila, 3:12 está más cerca de 2:58 que 3:55. En base a qué hacer de asignar 3:55? Si no hay reglas, es difícil de combinar.
  • Hola Arun/Roland. Gracias por tus comentarios. Arun – puedo asignar 3:12 3:55 como el deseo de que todos los dts1 valores para coincidir con el más cercano hh:mm fila en dts2 más grande que sí mismo, a menos que el valor en dts1 está a menos de 5 minutos más de la hora:min fila en dts2 procedimiento (ejemplo abajo). Lo siento, no estoy seguro de cómo proporcionar un dput de salida.
InformationsquelleAutor Emily | 2013-03-04

2 Comentarios

  1. 6

    Después de la primera conversión de su datetime cadenas de caracteres para POSIXt clases, alguna combinación de rounding y truncador aquellos tiempos, debería obtener algo que usted puede utilizar como la base de una combinación.

    Primera lectura de los datos, y crear los correspondientes POSIXt datetimes:

    dts1 <- structure(list(datetime = structure(1:6,
    .Label = c("30/03/2011 02:32", "30/03/2011 02:42",
    "30/03/2011 02:52", "30/03/2011 03:02", "30/03/2011 03:12",
    "30/03/2011 03:22"), class = "factor"), count = c(27L, 3L,
    0L, 1L, 15L, 0L), period = c(561L, 600L, 574L, 550L, 600L,
    597L)), .Names = c("datetime", "count", "period"),
    class = "data.frame", row.names = c(NA, -6L))
    dts2 <- structure(list(datetime = structure(1:7,
    .Label = c("30/03/2011 01:59", "30/03/2011 02:58",
    "30/03/2011 03:55", "30/03/2011 04:53", "30/03/2011 05:52",
    "30/03/2011 06:48", "30/03/2011 07:48"), class = "factor"),
    dist = c(23.9, 14.7, 10.4, 35.4, 56.1, 12.3, 10.7), car =
    c(1L, 1L, 2L, 1L, 1L, 1L, 1L), satd = c(3L, 7L, 9L, 3L, 7L,
    4L, 5L), alt = c(1.76, 6.36, -0.34, 3.55, -0.91, 6.58,
    4.18)), .Names = c("datetime", "dist", "car", "satd",
    "alt"), class = "data.frame", row.names = c(NA, -7L))
    # create corresponding POSIXlt vector
    # (you could update the 'datetime' columns in-place if you prefer)
    datetime1 <- strptime(dts1$datetime, format="%d/%m/%Y %H:%M")
    datetime2 <- strptime(dts2$datetime, format="%d/%m/%Y %H:%M")

    El siguiente código produce una fusión de la tabla se basa en la hora más cercana en todos los casos. Dentro de la combinación es simplemente anteponiendo una columna con la parte redondeada de veces a cada uno de los marcos de datos, la fusión basa en que (es decir, el número de columna 1), a continuación, utilizando el -1 índice de eliminar la columna al final:

    # merge based on nearest hour
    merge(
    cbind(round(datetime1, "hours"), dts1),
    cbind(round(datetime2, "hours"), dts2),
    by=1, suffixes=c("_dts1", "_dts2")
    )[-1]
    datetime_dts1 count period    datetime_dts2 dist car satd  alt
    1 30/03/2011 02:32    27    561 30/03/2011 02:58 14.7   1    7 6.36
    2 30/03/2011 02:42     3    600 30/03/2011 02:58 14.7   1    7 6.36
    3 30/03/2011 02:52     0    574 30/03/2011 02:58 14.7   1    7 6.36
    4 30/03/2011 03:02     1    550 30/03/2011 02:58 14.7   1    7 6.36
    5 30/03/2011 03:12    15    600 30/03/2011 02:58 14.7   1    7 6.36
    6 30/03/2011 03:22     0    597 30/03/2011 02:58 14.7   1    7 6.36

    Como en el anterior, pero esta vez sólo truncar en horas:

    merge(
    cbind(trunc(datetime1, "hours"), dts1),
    cbind(trunc(datetime2, "hours"), dts2),
    by=1, suffixes=c("_dts1", "_dts2")
    )[-1]
    datetime_dts1 count period    datetime_dts2 dist car satd   alt
    1 30/03/2011 02:32    27    561 30/03/2011 02:58 14.7   1    7  6.36
    2 30/03/2011 02:42     3    600 30/03/2011 02:58 14.7   1    7  6.36
    3 30/03/2011 02:52     0    574 30/03/2011 02:58 14.7   1    7  6.36
    4 30/03/2011 03:02     1    550 30/03/2011 03:55 10.4   2    9 -0.34
    5 30/03/2011 03:12    15    600 30/03/2011 03:55 10.4   2    9 -0.34
    6 30/03/2011 03:22     0    597 30/03/2011 03:55 10.4   2    9 -0.34

    Como en el anterior, pero para dts1 tratar el expediente como pertenecientes a la hora anterior hasta 10 minutos después de la hora, restando 10*60 segundos antes de truncar. Este produce el mismo resultado que ha especificado, aunque sin más información que yo no estoy seguro de que es una regla exacta que usted desea.

    merge(
    cbind(trunc(datetime1 - 10*60, "hours"), dts1),
    cbind(trunc(datetime2, "hours"), dts2),
    by=1, suffixes=c("_dts1", "_dts2")
    )[-1]
    datetime_dts1 count period    datetime_dts2 dist car satd   alt
    1 30/03/2011 02:32    27    561 30/03/2011 02:58 14.7   1    7  6.36
    2 30/03/2011 02:42     3    600 30/03/2011 02:58 14.7   1    7  6.36
    3 30/03/2011 02:52     0    574 30/03/2011 02:58 14.7   1    7  6.36
    4 30/03/2011 03:02     1    550 30/03/2011 02:58 14.7   1    7  6.36
    5 30/03/2011 03:12    15    600 30/03/2011 03:55 10.4   2    9 -0.34
    6 30/03/2011 03:22     0    597 30/03/2011 03:55 10.4   2    9 -0.34

    Usted puede ajustar los detalles de cuáles ronda, que se trunca, y si por primera vez de restar/añadir algo de tiempo, dependiendo de su normativa específica.

    Edición:

    No es el más elegante, pero aquí es un enfoque diferente que se adapta a las más complicadas condicional de la regla que describe en sus comentarios. Este se apoya fuertemente en na.locf del zoológico del paquete para determinar primero que dts2 los tiempos, antes y después de cada dts1 registro. Con esos en la mano, es sólo una cuestión de la aplicación de la regla para seleccionar el que desee dts2 tiempo, la coincidencia de volver a la original dts1 la tabla, entonces la fusión.

    library(zoo)
    # create ordered list of all datetimes, using names to keep
    # track of which ones come from each data frame
    alldts <- sort(c(
    setNames(datetime1, rep("dts1", length(datetime1))),
    setNames(datetime2, rep("dts2", length(datetime2)))))
    is.dts1 <- names(alldts)=="dts1"
    # for each dts1 record, get previous closest dts2 time
    dts2.prev <- alldts
    dts2.prev[is.dts1] <- NA
    dts2.prev <- na.locf(dts2.prev, na.rm=FALSE)[is.dts1]
    # for each dts1 record, get next closest dts2 time
    dts2.next <- alldts
    dts2.next[is.dts1] <- NA
    dts2.next <- na.locf(dts2.next, na.rm=FALSE, fromLast=TRUE)[is.dts1]
    # for each dts1 record, apply rule to choose dts2 time
    use.prev <- !is.na(dts2.prev) & (alldts[is.dts1] - dts2.prev < 5)
    dts2.to.use <- ifelse(use.prev, as.character(dts2.prev), 
    as.character(dts2.next))
    # merge based on chosen dts2 times, prepended as character vector
    # for the purpose of merging
    merge(
    cbind(.dt=dts2.to.use[match(datetime1, alldts[is.dts1])], dts1),
    cbind(.dt=as.character(datetime2), dts2),
    by=".dt", all.x=TRUE, suffixes=c("_dts1", "_dts2")
    )[-1]
    • Gracias por sus sugerencias regetz. Muy útil. El problema con la resta de 10*60 antes de truncar es que sólo tiene en cuenta la hora, los minutos. Mi hora valores en dts2 no siempre son de 60 minutos de duración. En cambio, quiero que la secuencia de comandos para buscar en cada fila en dts1 y coinciden a la hora más cercana:min fila en dts2 que es más grande que sí mismo, a menos que el valor en dts1 está a menos de 5 minutos más de la hora:min fila en dts2 procedimiento.
    • Un Ejemplo: 30/03/2011 03:32 igualado a 30/03/2011 03:49, 30/03/2011 03:42 igualado a 30/03/2011 03:49, 30/03/2011 03:52 igualado a 30/03/2011 03:49, 30/03/2011 04:02 igualado a 30/03/2011 04:42 y así sucesivamente….
    • Excelente, esto es exactamente lo que yo estaba buscando. Muchas gracias por tu extensa respuesta. Muy apreciada!
    • Esta fue una increíble respuesta, gracias!
  2. 0

    El selector de datos.tabla parece muy adecuado para eso. Es muy eficiente y permite combinar el valor más próximo (superior o inferior o ambos).

    Encontrar en esta página web: https://www.r-bloggers.com/understanding-data-table-rolling-joins/ ejemplo para la izquierda, a la derecha se une…etc

    website[, join_time:=session_start_time]
    paypal[, join_time:=purchase_time]
    setkey(website, name, join_time)
    setkey(paypal, name, join_time)
    website[paypal, roll = T]

    Sobre DT: https://cran.r-project.org/web/packages/data.table/vignettes/datatable-intro.html

Dejar respuesta

Please enter your comment!
Please enter your name here