2012-01-20 9 views
13

Estoy tratando de crear un subconjunto de un marco de datos y, cuando lo hago, R cambia el formato de la columna de fecha. ¿Alguna idea de por qué o cómo solucionar esto?cbind() está cambiando el formato de fecha

> head(spyPr2) 
     Date Open High Low Close Volume Adj.Close 
1 12/30/2011 126.02 126.33 125.50 125.50 95599000 125.50 
2 12/29/2011 125.24 126.25 124.86 126.12 123507200 126.12 
3 12/28/2011 126.51 126.53 124.73 124.83 119107100 124.83 
4 12/27/2011 126.17 126.82 126.06 126.49 86075700 126.49 
5 12/23/2011 125.67 126.43 125.41 126.39 92187200 126.39 
6 12/22/2011 124.63 125.40 124.23 125.27 119465400 125.27 
> spyPr2$Date <- as.Date(spyPr2$Date, format = "%m/%d/%Y") 
> head(spyPr2) 
     Date Open High Low Close Volume Adj.Close 
1 2011-12-30 126.02 126.33 125.50 125.50 95599000 125.50 
2 2011-12-29 125.24 126.25 124.86 126.12 123507200 126.12 
3 2011-12-28 126.51 126.53 124.73 124.83 119107100 124.83 
4 2011-12-27 126.17 126.82 126.06 126.49 86075700 126.49 
5 2011-12-23 125.67 126.43 125.41 126.39 92187200 126.39 
6 2011-12-22 124.63 125.40 124.23 125.27 119465400 125.27 
> spyPr2 <- data.frame(cbind(spyPr2$Date, spyPr2$Close, spyPr2$Adj.Close)) 
> str(spyPr2) 
'data.frame': 1638 obs. of 3 variables: 
$ X1: num 15338 15337 15336 15335 15331 ... 
$ X2: num 126 126 125 126 126 ... 
$ X3: num 126 126 125 126 126 ... 
> head(spyPr2) 
    X1  X2  X3 
1 15338 125.50 125.50 
2 15337 126.12 126.12 
3 15336 124.83 124.83 
4 15335 126.49 126.49 
5 15331 126.39 126.39 
6 15330 125.27 125.27 

ACTUALIZACIÓN:

> spyPr2 <- data.frame(cbind(spyPr2["Date"], spyPr2$Close, spyPr2$Adj.Close)) 
Error in `[.data.frame`(spyPr2, "Date") : undefined columns selected 
> spyPr2 <- data.frame(cbind(spyPr2[,"Date"], spyPr2$Close, spyPr2$Adj.Close)) 
Error in `[.data.frame`(spyPr2, , "Date") : undefined columns selected 

ACTUALIZACIÓN 2:

structure(list(Date = structure(c(15338, 15337, 15336, 15335, 
15331, 15330), class = "Date"), Open = c(126.02, 125.24, 126.51, 
126.17, 125.67, 124.63), High = c(126.33, 126.25, 126.53, 126.82, 
126.43, 125.4), Low = c(125.5, 124.86, 124.73, 126.06, 125.41, 
124.23), Close = c(125.5, 126.12, 124.83, 126.49, 126.39, 125.27 
), Volume = c(95599000L, 123507200L, 119107100L, 86075700L, 92187200L, 
119465400L), Adj.Close = c(125.5, 126.12, 124.83, 126.49, 126.39, 
125.27)), .Names = c("Date", "Open", "High", "Low", "Close", 
"Volume", "Adj.Close"), row.names = c(NA, -6L), class = "data.frame") 
+0

¿Has probado usar '[' selection en vez de '$'? ej. 'spyPr2 [" Date "]' – James

+0

Muéstranos los resultados de 'dput (head (spyPr2))' para que no tengamos que preocuparnos de crear nuestros propios datos para ver qué está sucediendo. Sospecho que el método 'cbind()' predeterminado es el problema aquí, pero me gustaría ejecutar el código en mi propia máquina para verificar. –

+0

No, lo siento, me refería a la salida de 'dput()' * antes de * procesarlo. Es decir. Give es su información de entrada (pero solo necesitamos las 6 líneas que muestra. –

Respuesta

41

respuesta obvia es no lo haga de subconjuntos de esa manera! Use las herramientas apropiadas. ¿Cuál es incorrecto con

spyPr2.new <- spyPr2[, c("Date", "Close", "Adj.Close")] 

? Para explicar el comportamiento que está viendo, necesita comprender qué devuelve $ y cómo funciona cbind(). cbind() es una de esas rarezas en el que R método de envío no se realiza mediante el método habitual sino que se maneja a través de un código especial enterrado en la parte interna de R. Este es todo el código R detrás cbind():

> cbind 
function (..., deparse.level = 1) 
.Internal(cbind(deparse.level, ...)) 
<bytecode: 0x24fa0c0> 
<environment: namespace:base> 
No

mucho ayuda, ¿eh? Existen métodos para tramas de datos y "ts" objetos sin embargo:

> methods(cbind) 
[1] cbind.data.frame cbind.ts*  

    Non-visible functions are asterisked 

antes de hacer la revelación, nota también lo $ retornos (dat2 Es el 6 líneas de datos después de la conversión de Date a un objeto "Date"):

> str(dat2$Date) 
Date[1:6], format: "2011-12-30" "2011-12-29" "2011-12-28" "2011-12-27" ... 

Este es un objeto "Date", que es realmente un vector especial.

> class(dat2$Date) 
[1] "Date" 

La clave es que es no una trama de datos. Entonces, cuando usa cbind(), el código interno ve tres vectores y el código interno crea una matriz.

> (c1 <- cbind(dat2$Date, dat2$Close, dat2$Adj.Close)) 
     [,1] [,2] [,3] 
[1,] 15338 125.50 125.50 
[2,] 15337 126.12 126.12 
[3,] 15336 124.83 124.83 
[4,] 15335 126.49 126.49 
[5,] 15331 126.39 126.39 
[6,] 15330 125.27 125.27 
> class(c1) 
[1] "matrix" 

Sólo puede haber matrices numéricas o de caracteres en R de modo que el objeto Date se convierte en un vector numérico:

> as.numeric(dat2$Date) 
[1] 15338 15337 15336 15335 15331 15330 

para permitir cbind() para producir una matriz numérica.

Puede forzar el uso del método trama de datos llamando explícitamente y lo hace saber cómo manejar "Date" objetos y así no hace ningún tipo de conversión:

> cbind.data.frame(dat2$Date, dat2$Close, dat2$Adj.Close) 
    dat2$Date dat2$Close dat2$Adj.Close 
1 2011-12-30  125.50   125.50 
2 2011-12-29  126.12   126.12 
3 2011-12-28  124.83   124.83 
4 2011-12-27  126.49   126.49 
5 2011-12-23  126.39   126.39 
6 2011-12-22  125.27   125.27 

Sin embargo, toda la explicación a un lado, está intentando hacer el subconjunto de una manera muy compleja.[ en función subconjunto funciona bien:

> dat2[, c("Date", "Close", "Adj.Close")] 
     Date Close Adj.Close 
1 2011-12-30 125.50 125.50 
2 2011-12-29 126.12 126.12 
3 2011-12-28 124.83 124.83 
4 2011-12-27 126.49 126.49 
5 2011-12-23 126.39 126.39 
6 2011-12-22 125.27 125.27 

subset() es también una opción, pero no para continuar:

> subset(dat2, select = c("Date", "Close", "Adj.Close")) 
     Date Close Adj.Close 
1 2011-12-30 125.50 125.50 
2 2011-12-29 126.12 126.12 
3 2011-12-28 124.83 124.83 
4 2011-12-27 126.49 126.49 
5 2011-12-23 126.39 126.39 
6 2011-12-22 125.27 125.27 
+0

Eso fue todo. Muchas gracias. Ni siquiera pensé en hacerlo de esa manera. – screechOwl

+3

cbind.data.frame es útil para fusionar columnas de fecha en otras contextos también. – etov

+0

Impresionante! Y gracias por proporcionar el método 'cbind.data.frame'. Tuve que hacer un cbind en columnas de diferentes tablas, por lo tanto, no pude usar el método de subconjunto. –

4

Creo que podría llamar a esto una instancia oculta de la drop = FALSE Gotcha con tramas de datos.

Cuando usa cbind, solo utiliza el método de marco de datos si al menos uno de los componentes también son marcos de datos. De lo contrario, todo se convierte en un solo tipo para construir una matriz.

Por lo tanto, llamar cbind en elementos como spyPr2$Date o spyPr2[,'Date'] resultará en una matriz (pérdida de la estructura de la fecha), que no será mágicamente restaurada envolviéndolo todo en data.frame.

Puede hacer esto si usa [ para seleccionar cada columna, pero solo usando drop = FALSE que evita que R convierta el resultado en un vector (que le devuelve directamente donde comenzó con R forzando el resultado a una matriz) :

cbind(spyPr2[,'Date',drop = FALSE],spyPr2[,'Close']) 

es suficiente, ya que solo necesita uno de los componentes para ser un marco de datos.

Pero Gavin está en lo correcto en general, no debería estar subconjunto su marco de datos de esta manera.