Cbind() изменяет форматирование даты
Я пытаюсь создать подмножество фрейма данных, и когда я это сделаю, R переключает форматирование столбца даты. Любая идея, почему и как это исправить?
> 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
UPDATE:
> 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
ОБНОВЛЕНИЕ 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")
Ответы
Ответ 1
Очевидный ответ не делает подмножества вроде этого! Используйте соответствующие инструменты. Что не так с
spyPr2.new <- spyPr2[, c("Date", "Close", "Adj.Close")]
?
Чтобы объяснить поведение, которое вы видите, вам нужно понять, что возвращает $
и как работает cbind()
. cbind()
является одной из тех странностей в R, где отправка метода не выполняется обычным способом, а обрабатывается через специальный код, закодированный во внутренних элементах R. Это все код R за cbind()
:
> cbind
function (..., deparse.level = 1)
.Internal(cbind(deparse.level, ...))
<bytecode: 0x24fa0c0>
<environment: namespace:base>
Не очень помогает, а? Однако существуют методы для кадров данных и "ts"
объектов:
> methods(cbind)
[1] cbind.data.frame cbind.ts*
Non-visible functions are asterisked
Прежде чем я открою, обратите внимание, что возвращает $
(dat2
- это ваши 6 строк данных после преобразования Date
в объект "Date"
):
> str(dat2$Date)
Date[1:6], format: "2011-12-30" "2011-12-29" "2011-12-28" "2011-12-27" ...
Это объект "Date"
, который действительно является специальным вектором.
> class(dat2$Date)
[1] "Date"
Главное, что это не кадр данных. Поэтому, когда вы используете cbind()
, внутренний код видит три вектора, а внутренний код создает матрицу.
> (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"
В R могут быть только числовые или символьные матрицы, поэтому объект Date
преобразуется в числовой вектор:
> as.numeric(dat2$Date)
[1] 15338 15337 15336 15335 15331 15330
чтобы позволить cbind()
создавать числовую матрицу.
Вы можете принудительно использовать метод фрейма данных, вызвав его явно, и он знает, как обрабатывать объекты "Date"
и поэтому не делает никакого преобразования:
> 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
Однако, все объяснения в стороне, вы пытаетесь сделать подмножество очень сложным образом. [
как функция подмножества отлично работает:
> 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()
также является необязательным:
> 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
Ответ 2
Я думаю, что я мог бы назвать это скрытым экземпляром drop = FALSE
gotcha с кадрами данных.
Когда вы используете cbind
, он использует только метод данных, если хотя бы один из компонентов также является фреймами данных. В противном случае для построения матрицы все преобразуется в один тип.
Таким образом, вызов cbind
для таких элементов, как spyPr2$Date
или spyPr2[,'Date']
, приведет к матрице (теряющей структуру дат), которая не будет восстановлена магией, обернув ее все в data.frame
.
Вы можете сделать это, если вы используете [
для выбора каждого столбца, но только с помощью drop = FALSE
, который предотвращает преобразование R результата в вектор (который приземляет вас прямо туда, где вы начали с R, принуждающего результат к матрица):
cbind(spyPr2[,'Date',drop = FALSE],spyPr2[,'Close'])
достаточно, так как вам нужен только один из компонентов, который должен быть кадром данных.
Но Гэвин прав вообще, вы не должны подражать вашему кадру данных таким образом.