【问题标题】:cbind() is changing date formattingcbind() 正在改变日期格式
【发布时间】:2012-02-15 04:51:25
【问题描述】:

我正在尝试创建数据框的子集,当我这样做时,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

更新:

> 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")

【问题讨论】:

  • 您是否尝试过使用[ 选择而不是$?例如spyPr2["Date"]
  • 向我们展示dput(head(spyPr2)) 的结果,这样我们就不必费心创建自己的数据来查看发生了什么。我怀疑默认的cbind() 方法是这里的问题,但我想在我自己的机器上运行代码来检查。
  • 不,对不起,我的意思是来自dput()的输出你处理它之前。 IE。 Give 是您的输入数据(但我们只需要您显示的 6 行。

标签: r date


【解决方案1】:

明显的答案是不要那样做子集!使用适当的工具。有什么问题

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

?

要解释您看到的行为,您需要了解$ 返回的内容以及cbind() 的工作原理。 cbind() 是 R 中的奇怪之处之一,其中方法调度不是通过通常的方法完成,而是通过隐藏在 R 内部的特殊代码进行处理。这是 cbind() 背后的所有 R 代码:

> 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 是将Date 转换为"Date" 对象后的 6 行数据):

> 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

【讨论】:

  • 做到了。非常感谢。甚至没有想过这样做。
  • cbind.data.frame 也有助于在其他上下文中合并日期列。
  • 太棒了!并感谢您提供cbind.data.frame 方法。我不得不对来自不同表的列进行 cbind,因此不能使用子集方法。
【解决方案2】:

我想我可以将其称为带有数据框的 drop = FALSE 陷阱的隐藏实例。

当你使用cbind时,如果至少有一个组件也是数据框,它只使用数据框方法。否则,所有内容都将转换为单一类型以构造矩阵。

因此,在spyPr2$DatespyPr2[,'Date'] 等元素上调用cbind 将产生一个矩阵(丢失日期结构),它不会通过将其全部包装在data.frame 中而神奇地恢复。

如果您使用 [ 选择每一列,则可以执行此操作,但只能使用 drop = FALSE 防止 R 将结果转换为向量(这会让您回到您开始的地方,R 将结果强制转换为一个矩阵):

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

就足够了,因为您只需要将其中一个组件作为数据框。

但总的来说,Gavin 是对的,您不应该以这种方式对数据框进行子集化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多