首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建POSIXct矩阵

如何创建POSIXct矩阵
EN

Stack Overflow用户
提问于 2016-02-03 08:51:24
回答 4查看 1.4K关注 0票数 2

当我在R3.1.2中创建给定POSIXct向量的矩阵时,矩阵的条目是数字的,而不是POSIXct:

代码语言:javascript
复制
x <- as.POSIXct("2012-02-25 19:00:00")
x
attributes(x)

m <- matrix(x, nrow=2, ncol=3)
m
attributes(m)

创建POSIXct值矩阵的最佳方法是什么?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-02-03 09:50:31

我想我以前从未见过有人创建一个POSIXct值矩阵,尽管很难想象这样一个对象的用例。

R似乎不太支持这种类型的对象。S3对象系统非常有限,创建POSIXct矩阵需要同时设置矩阵和POSIXct (和POSIXt,这似乎总是与POSIXct一起标记) S3类。事实上,在我的经验中,任何对象继承多个显式S3类都是很不寻常的,也许除了POSIXct+POSIXt和POSIXlt+POSIXt之外。

我已经尝试通过创建一个新的矩阵构造函数matrix.POSIXct()来缓冲这种类型的对象。为了方便起见,为了提供S3调度,我还创建了一个新的通用matrix()和默认matrix.default(),它将委托给正常的base::matrix()。注意,matrix()的这种泛化有时是由R包(如gmp )完成的。它们将它们的泛化功能限制在它们的包环境中,但我只是将这些函数转储到全局环境中。

不幸的是,默认的POSIXct打印函数print.POSIXct()不够聪明,无法处理同样被归类为矩阵的POSIXct向量,因此任何这样的矩阵都会打印为普通的旧向量。为了解决这个问题,我还创建了一个新的print.POSIXct()函数,该函数拦截任何POSIXct类对象的打印,并检查它是否也被归类为一个矩阵,在这种情况下,为了以最小的工作量提供一个合理的实现,我构建了一个新的矩阵,其数据值由POSIXct值的字符表示组成,然后打印该矩阵。如果没有将其归类为矩阵,我只需将参数传递给普通的base::print.POSIXct()函数,以打印普通的非矩阵POSIXct向量。

我试图尽可能密切地跟踪base::matrix()的设计,以避免在matrix.POSIXct()中出现默认的缺失参数。

代码语言:javascript
复制
matrix <- function(x,...) UseMethod('matrix');
matrix.default <- function(...) base::matrix(...);

matrix.POSIXct <- function(data=NA,nrow,ncol,byrow=F,dimnames=NULL,...) {
    if (missing(nrow)) {
        if (missing(ncol)) {
            nrow <- length(data);
            ncol <- 1L;
        } else {
            nrow <- ceiling(length(data)/ncol);
        }; ## end if
    } else {
        if (missing(ncol))
            ncol <- ceiling(length(data)/nrow);
    }; ## end if
    data <- rep(as.POSIXct(data,tz=attr(data,'tzone'),...),len=nrow*ncol);
    if (byrow) {
        dim(data) <- c(ncol,nrow);
        data <- t(data);
    } else
        dim(data) <- c(nrow,ncol);
    if (!is.null(dimnames))
        base::dimnames(data) <- dimnames;
    class(data) <- c(class(data),'matrix');
    data;
}; ## end matrix.POSIXct()

print.POSIXct <- function(x,...) {
    if (inherits(x,'matrix') && !is.null(nrow(x))) {
        print(matrix(as.character(x,usetz=T),nrow(x),dimnames=dimnames(x)),...);
        invisible(x);
    } else
        base::print.POSIXct(x,...);
}; ## end print.POSIXct()

对您的数据进行演示:

代码语言:javascript
复制
x <- as.POSIXct('2012-02-25 19:00:00');
m <- matrix(x,2L,3L);
m;
##      [,1]                      [,2]                      [,3]
## [1,] "2012-02-25 19:00:00 EST" "2012-02-25 19:00:00 EST" "2012-02-25 19:00:00 EST"
## [2,] "2012-02-25 19:00:00 EST" "2012-02-25 19:00:00 EST" "2012-02-25 19:00:00 EST"
attributes(m);
## $class
## [1] "POSIXct" "POSIXt"  "matrix"
##
## $tzone
## [1] ""
##
## $dim
## [1] 2 3

这是一个format.POSIXct()

代码语言:javascript
复制
format.POSIXct <- function(x,...) {
    if (inherits(x,'matrix') && !is.null(nrow(x)))
        matrix(base::format.POSIXct(x,...),nrow(x),dimnames=dimnames(x))
    else
        base::format.POSIXct(x,...);
}; ## end format.POSIXct()

好吧,忘了索引了。这是另一个有问题的案例。默认的base::`[.POSIXct`()索引函数比较便宜(诚然,类似于我上面的一些shim代码),因为它只是暂时删除了向量的类,传递给下一个特定于S3的类,然后恢复原始类。这意味着矩阵的drop参数受到尊重,如果设置为TRUE (默认值),并且下标被删除,则意味着从返回的对象中删除dim属性。

问题是廉价包装器中的类恢复了我们的矩阵类,因此,当廉价包装器返回时,我们收到一个没有dim属性的矩阵类对象。

如果和当我们试图打印子设置向量时,我们所遇到的确切错误(如果和当我们试图打印子设置向量时,print.POSIXct() shim会发出这个错误(“在为函数‘print’选择方法时计算参数'x‘时出错:基本错误::矩阵(.):非数字矩阵范围”)是由nrow(x)返回NULL引起的,因此matrix()调用接收nrow=NULL。

我做了两件事来解决这个问题。首先,我改进了print.POSIXct()函数,以防止nrow(x)返回NULL的情况,在这种情况下,它不会将对象打印为矩阵。因此,如果它收到一个没有dim属性的矩阵类对象(尽管这种情况不应该发生),它就会将它打印为一个普通的旧POSIXct向量。

其次,我编写了另一个索引函数来检测dim属性的删除,并在这种情况下相应地删除矩阵类。

这个新函数的创建很复杂,因为廉价包装器使用NextMethod()来调用下一个特定于S3的函数,如果从直接调用的调用中调用该函数,则无效,而不依赖于S3调度过程。因此,正如您在下面的代码中所看到的,我使用了一些技巧将廉价包装器的主体“插入”到我们的shim函数中,从而将NextMethod()调用移动到我们的shim中,因此必须通过泛型`[`() (通常)调用该调用:

代码语言:javascript
复制
`[.POSIXct` <- function(x,...) {
    res <- blah;
    if (inherits(x,'matrix') && !'dim'%in%names(attributes(res)))
        class(res) <- class(res)[class(res)!='matrix'];
    res;
};
body(`[.POSIXct`)[[2]][[3]] <- body(base::`[.POSIXct`);

演示:

代码语言:javascript
复制
x <- as.POSIXct('2016-02-05 00:00:00')+0:8;
m <- matrix(x,3L,byrow=T);
m;
##      [,1]                      [,2]                      [,3]
## [1,] "2016-02-05 00:00:00 EST" "2016-02-05 00:00:01 EST" "2016-02-05 00:00:02 EST"
## [2,] "2016-02-05 00:00:03 EST" "2016-02-05 00:00:04 EST" "2016-02-05 00:00:05 EST"
## [3,] "2016-02-05 00:00:06 EST" "2016-02-05 00:00:07 EST" "2016-02-05 00:00:08 EST"
m[1];
## [1] "2016-02-05 EST"
m[1:3];
## [1] "2016-02-05 00:00:00 EST" "2016-02-05 00:00:03 EST" "2016-02-05 00:00:06 EST"
m[1:3,1];
## [1] "2016-02-05 00:00:00 EST" "2016-02-05 00:00:03 EST" "2016-02-05 00:00:06 EST"
m[1:3,1,drop=F];
##      [,1]
## [1,] "2016-02-05 00:00:00 EST"
## [2,] "2016-02-05 00:00:03 EST"
## [3,] "2016-02-05 00:00:06 EST"
m[1:3,1:2];
##      [,1]                      [,2]
## [1,] "2016-02-05 00:00:00 EST" "2016-02-05 00:00:01 EST"
## [2,] "2016-02-05 00:00:03 EST" "2016-02-05 00:00:04 EST"
## [3,] "2016-02-05 00:00:06 EST" "2016-02-05 00:00:07 EST"

这是一个as.data.frame.POSIXct()

代码语言:javascript
复制
as.data.frame.POSIXct <- function(x,...) {
    if (inherits(x,'matrix') && !is.null(dim(x))) {
        class(x) <- class(x)[!class(x)%in%c('POSIXct','POSIXt')];
        res <- as.data.frame(x,...);
        for (ci in seq_along(res))
            res[[ci]] <- as.POSIXct(res[[ci]],tz=attr(x,'tzone'),origin='1970-01-01');
        res;
    } else
        base::as.data.frame.POSIXct(x,...);
}; ## end as.data.frame.POSIXct()

演示:

代码语言:javascript
复制
m <- matrix(as.POSIXct('2016-02-05 00:00:00')+0:8,3);
m;
##      [,1]                      [,2]                      [,3]
## [1,] "2016-02-05 00:00:00 EST" "2016-02-05 00:00:03 EST" "2016-02-05 00:00:06 EST"
## [2,] "2016-02-05 00:00:01 EST" "2016-02-05 00:00:04 EST" "2016-02-05 00:00:07 EST"
## [3,] "2016-02-05 00:00:02 EST" "2016-02-05 00:00:05 EST" "2016-02-05 00:00:08 EST"
as.data.frame(m);
##                    V1                  V2                  V3
## 1 2016-02-05 00:00:00 2016-02-05 00:00:03 2016-02-05 00:00:06
## 2 2016-02-05 00:00:01 2016-02-05 00:00:04 2016-02-05 00:00:07
## 3 2016-02-05 00:00:02 2016-02-05 00:00:05 2016-02-05 00:00:08

这是一个summary.POSIXct()

代码语言:javascript
复制
summary.POSIXct <- function(x,...) {
    if (inherits(x,'matrix') && !is.null(dim(x)))
        summary(as.data.frame(x),...)
    else
        base::summary.POSIXct(x,...);
}; ## end summary.POSIXct()
票数 9
EN

Stack Overflow用户

发布于 2016-02-03 08:55:02

粗略的方法是将类和属性重新分配到矩阵中:

代码语言:javascript
复制
x <- as.POSIXct("2012-02-25 19:00:00")
m <- matrix(x, nrow=2, ncol=3)
assignPOSIXct <- function(m,x){
    class(m) <- c("matrix",class(x)) 
    attr(m,"tzone") <- attr(x,"tzone")
    return(m)
}
m <- assignPOSIXct(m,x)
m

但这很麻烦,而且容易出错。在循环中,我必须检查条目是否为POSIXct。

票数 0
EN

Stack Overflow用户

发布于 2016-02-05 08:00:54

另一个方法是接受在存储到矩阵和数组时放松S3信息,并在需要时转换为POSIXct。这可以通过以下函数来完成

代码语言:javascript
复制
asPOSIXctFromNumeric <- function(
    ### convert numeric to POSIXct with default origin and time zone 
    x       ##<< numeric vector to convert
    ,origin='1970-01-01'    ##<< default origin
    ,tz='GMT'               ##<< default time zone
){
    ##details<<
    ## Sometime POSIXct becomes converted to numeric, e.g. when stored
    ## in a matrix.
    ## The defaults of this routing convert it back to POSIXct with      
    ## the same origin, and a default time zone
    as.POSIXct(as.numeric(x),origin=origin, tz=tz)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35172317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档