2010-12-08 22 views
18

Estoy intentando transformar dos columnas en mi dataframe en la clase de tiempo 'buena' &, y hasta ahora no tuve mucho éxito con eso. Probé varias clases (timeDate, Date, timeSeries, POSIXct, POSIXlt) pero sin éxito. Tal vez solo estoy pasando por alto lo obvio y porque he intentado tantos enfoques que ya no sé qué es qué más. Espero que algunos de ustedes puedan arrojar algo de luz sobre dónde me equivoco.Cómo encontrar la fecha más alta (más reciente) y la más baja (anterior) [R]

Objetivo: Quiero calcular la diferencia entre dos fechas utilizando la fecha más temprana y la más reciente. Lo hice trabajando con head() y tail(), pero como esos valores no son necesarios, la fecha más temprana y la última en mis datos, necesito otra forma. (No puedo hacer que la ordenación de datos funcione, porque ordena los datos solo el día de la fecha.)

Segundo objetivo: Quiero convertir las fechas del formato diario (es decir, 8-12 -2010) a niveles semanales, mensuales y anuales (es decir, '49 -2010 ',' diciembre-10 'y solo' 2010 '). Esto se puede hacer con la configuración de formato (como "% d-% m-% y"). ¿Se puede hacer esto convirtiendo el data.frame en una clase de tiempo, y luego transformando la clase de tiempo en el formato correcto (8-12-2010 -> format ("% B-% y") -> 'december-10') , y luego transformando esa clase de tiempo en un factor con niveles para cada mes?

Para ambos objetivos, necesito convertir la fecha de alguna manera a una clase de tiempo, y aquí es donde tuve algunas dificultades.

Mi trama de datos es el siguiente:

> tradesList[c(1,10,11,20),14:15] -> tmpTimes4 
> tmpTimes4 
    EntryTime ExitTime 
1 01-03-07 10-04-07 
10 29-10-07 02-11-07 
11 13-04-07 14-05-07 
20 18-12-07 20-02-08 

He aquí un resumen de lo que he intentado:

> class(tmpTimes4) 
[1] "data.frame" 
> as.Date(head(tmpTimes4$EntryTimes, n=1), format="%d-%m-%y") 
Error in as.Date.default(head(tmpTimes4$EntryTimes, n = 1), format = "%d-%m-%y") : 
    do not know how to convert 'head(tmpTimes4$EntryTimes, n = 1)' to class "Date" 
> as.timeDate(tmpTimes4, format="%d-%m-%y") 
Error in as.timeDate(tmpTimes4, format = "%d-%m-%y") : 
    unused argument(s) (format = "%d-%m-%y") 
> timeSeries(tmpTimes4, format="%d-%m-%y") 
Error in midnightStandard2(charvec, format) : 
    'charvec' has non-NA entries of different number of characters 
> tmpEntryTimes4 <- timeSeries(tmpTimes4$EntryTime, format="%d-%m-%y") 
> tmpExitTimes4 <- timeSeries(tmpTimes4$ExitTime, format="%d-%m-%y") 
> tmpTimes5 <- cbind(tmpEntryTimes4,tmpExitTimes4) 
> colnames(tmpTimes5) <- c("Entry","Exit") 
> tmpTimes5 
    Entry Exit  
[1,] 01-03-07 10-04-07 
[2,] 29-10-07 02-11-07 
[3,] 13-04-07 14-05-07 
[4,] 18-12-07 20-02-08 
> class(tmpTimes5) 
[1] "timeSeries" 
attr(,"package") 
[1] "timeSeries" 
> as.timeDate(tmpTimes5, format="%d-%m-%y") 
Error in as.timeDate(tmpTimes5, format = "%d-%m-%y") : 
    unused argument(s) (format = "%d-%m-%y") 
> as.Date(tmpTimes5, format="%d-%m-%y") 
Error in as.Date.default(tmpTimes5, format = "%d-%m-%y") : 
    do not know how to convert 'tmpTimes5' to class "Date" 
> format.POSIXlt(tmpTimes5, format="%d-%m-%y", usetz=FALSE) 
Error in format.POSIXlt(tmpTimes5, format = "%d-%m-%y", usetz = FALSE) : 
    wrong class 
> as.POSIXlt(tmpTimes5, format="%d-%m-%y", usetz=FALSE) 
Error in as.POSIXlt.default(tmpTimes5, format = "%d-%m-%y", usetz = FALSE) : 
    do not know how to convert 'tmpTimes5' to class "POSIXlt" 
> as.POSIXct(tmpTimes5, format="%d-%m-%y", usetz=FALSE) 
Error in as.POSIXlt.default(x, tz, ...) : 
    do not know how to convert 'x' to class "POSIXlt" 

Los paquetes TimeDate tiene una función de 'rango', sin embargo, la conversión a la La clase de fecha funciona para una instancia individual, pero por alguna razón no para un marco de datos:

> as.Date(tmpTimes4[1,1], format="%d-%m-%y") 
[1] "2007-03-01" 
> as.Date(tmpTimes4, format="%d-%m-%y") 
Error in as.Date.default(tmpTimes4, format = "%d-%m-%y") : 
    do not know how to convert 'tmpTimes4' to class "Date" 

En este momento, casi creo que es imposible de hacer, por lo que cualquier idea sería muy apreciada.

Saludos,

+0

Se podría usar 'dput (tmpTimes4)' para proporcionar un uso conjunto de datos exacta en el código. – Marek

+0

@Marek: ¡Gracias por responder! No sabía sobre dput, así que gracias por la propina. :) – Jura25

Respuesta

30

Start con algunos datos ficticios:

start <- as.Date("2010/01/01") 
end <- as.Date("2010/12/31") 
set.seed(1) 
datewant <- seq(start, end, by = "days")[sample(15)] 
tmpTimes <- data.frame(EntryTime = datewant, 
         ExitTime = datewant + sample(100, 15)) 
## reorder on EntryTime so in random order 
tmpTimes <- tmpTimes[sample(NROW(tmpTimes)), ] 
head(tmpTimes) 

así que tienen algo como esto:

> head(tmpTimes) 
    EntryTime ExitTime 
8 2010-01-14 2010-03-16 
9 2010-01-05 2010-01-17 
7 2010-01-10 2010-01-30 
3 2010-01-08 2010-04-16 
10 2010-01-01 2010-01-26 
13 2010-01-12 2010-02-15 

Utilizando lo anterior, mira Objetivo 1, diferencia de cómputo entre la fecha más temprana y la más reciente. Puede tratar las fechas como si fueran números (así es como se almacenan internamente de todos modos), por lo que funciones como min() y max() funcionarán. Puede utilizar la función difftime():

> with(tmpTimes, difftime(max(EntryTime), main(EntryTime))) 
Time difference of 14 days 

o utilizar restas estándar

> with(tmpTimes, max(EntryTime) - min(EntryTime)) 
Time difference of 14 days 

para obtener la diferencia en días. head() y tail() solo funcionarán si ordena las fechas, ya que toman el primer y el último valor en un vector, no el valor real más alto y más bajo.

Objetivo 2: Parece que intenta convertir un marco de datos en una Fecha. No puedes hacer esto. Lo que puede hacer es reformatear los datos en los componentes del marco de datos. Aquí agrego columnas al tmpTimes formateando la columna EntryTime en varios resúmenes diferentes de la fecha.

tmpTimes2 <- within(tmpTimes, weekOfYear <- format(EntryTime, format = "%W-%Y")) 
tmpTimes2 <- within(tmpTimes2, monthYear <- format(EntryTime, format = "%B-%Y")) 
tmpTimes2 <- within(tmpTimes2, Year <- format(EntryTime, format = "%Y")) 

Dar:

> head(tmpTimes2) 
    EntryTime ExitTime weekOfYear monthYear Year 
8 2010-01-14 2010-03-16 02-2010 January-2010 2010 
9 2010-01-05 2010-01-17 01-2010 January-2010 2010 
7 2010-01-10 2010-01-30 01-2010 January-2010 2010 
3 2010-01-08 2010-04-16 01-2010 January-2010 2010 
10 2010-01-01 2010-01-26 00-2010 January-2010 2010 
13 2010-01-12 2010-02-15 02-2010 January-2010 2010 

Si usted es estadounidense o si desea utilizar la convención de Estados Unidos para el comienzo de la semana (%W comienza la semana en lunes, en la convención de los Estados Unidos es comenzar en una Domingo), cambie el %W al %U. ?strftime tiene más detalles de lo que representan %W y %U.


Un punto final en formato de datos: En lo anterior he trabajado con fechas en formato estándar R. Tiene sus datos almacenados en un marco de datos en un marcado no estándar, presumiblemente como caracteres o factores. Entonces tiene algo como:

tmpTimes3 <- within(tmpTimes, 
        EntryTime <- format(EntryTime, format = "%d-%m-%y")) 
tmpTimes3 <- within(tmpTimes3, 
        ExitTime <- format(ExitTime, format = "%d-%m-%y")) 

> head(tmpTimes3) 
    EntryTime ExitTime 
8 14-01-10 16-03-10 
9 05-01-10 17-01-10 
7 10-01-10 30-01-10 
3 08-01-10 16-04-10 
10 01-01-10 26-01-10 
13 12-01-10 15-02-10 

Debe convertir esos caracteres o factores en algo que R entienda como una fecha. Mi preferencia sería la clase "Date". Antes de intentar las respuestas anteriores con sus datos, convertir los datos al formato correcto:

tmpTimes3 <- 
    within(tmpTimes3, { 
      EntryTime <- as.Date(as.character(EntryTime), format = "%d-%m-%y") 
      ExitTime <- as.Date(as.character(ExitTime), format = "%d-%m-%y") 
      }) 

por lo que sus datos se ve así:

> head(tmpTimes3) 
    EntryTime ExitTime 
8 2010-01-14 2010-03-16 
9 2010-01-05 2010-01-17 
7 2010-01-10 2010-01-30 
3 2010-01-08 2010-04-16 
10 2010-01-01 2010-01-26 
13 2010-01-12 2010-02-15 
> str(tmpTimes3) 
'data.frame': 15 obs. of 2 variables: 
$ EntryTime:Class 'Date' num [1:15] 14623 14614 14619 14617 14610 ... 
$ ExitTime :Class 'Date' num [1:15] 14684 14626 14639 14715 14635 ... 
+0

¡Guau Gavin, muchas gracias! Realmente me ayudaste, no solo con el ejemplo del código, sino también con el excelente (y claro) texto. Gracias de nuevo, ahora lo entiendo completamente, y lo logré calculando el número de días, transformando las fechas y mostrando los resuls por período de tiempo. ¡Sí! :) – Jura25

+0

@ Jura25: me alegro de que lo haya encontrado útil. –

+1

De hecho, trabajo mínimo y máximo para la fecha, pero si tiene alguna NA en su columna de fecha, súplicas usan na.rm = TRUE, p. fecha estelar <-min (DateofTest, na.rm = TRUE). Ahórrate el rasguño desconcertado en la cabeza. –

5

Respuesta corta:

  • Convert hasta la fecha si no está hecho.
  • Luego use min y max en la lista de las fechas.

    date_list = structure(c(15401, 15405, 15405), class = "Date") 
    date_list 
    #[1] "2012-03-02" "2012-03-06" "2012-03-06" 
    
    min(date_list) 
    #[1] "2012-03-02" 
    max(date_list) 
    #[1] "2012-03-06" 
    
Cuestiones relacionadas