在矩阵中使用VCTR
我正在试验在矩阵中使用VCTR,r,matrix,vctrs,R,Matrix,Vctrs,我正在试验vctrs包。我的实际用例在相关方面类似于vctrs主页上有用文章中实现的rational类,因为它使用rcrd进行配对数据。为了清晰起见,我会将其用于我的reprex。(编辑:然而,我对理性并不特别感兴趣。)让我先粘贴相关部分: 库(vctrs) 图书馆(热情地段) 新的理性的,理性的 #> [1,] 1/1 1/4 1/7 1/10 1/13 #> [2,] 1/2 1/5 1/8 1/11 1/14 #> [3,] 1/3 1/6 1/9 1/12 1/1
vctrs
包。我的实际用例在相关方面类似于vctrs
主页上有用文章中实现的rational
类,因为它使用rcrd
进行配对数据。为了清晰起见,我会将其用于我的reprex。(编辑:然而,我对理性并不特别感兴趣。)让我先粘贴相关部分:
库(vctrs)
图书馆(热情地段)
新的理性的,理性的
#> [1,] 1/1 1/4 1/7 1/10 1/13
#> [2,] 1/2 1/5 1/8 1/11 1/14
#> [3,] 1/3 1/6 1/9 1/12 1/15
这样,正常的矩阵运算将在m
上工作,例如
m[1,]
#>
#> 1/1 1/4 1/7 1/10 1/13
rational
类的整个设计似乎是建立在保护其类型安全性和对用户隐藏实现的基础上的,我可以看到这是使其一致工作所必需的,但这意味着您不能期望它与R的默认S3方法配合得很好
vctrs
的帮助文件特别指出
- dims(),dims只是一个想法,但我想知道,通过更清楚地定义“预期”的含义,您的问题是否可以得到改进。也许,“我如何修改我的对象
x
,或者为as.matrix
编写一个自定义方法,使x
的值成为矩阵的I,j
项?”或者您的“预期”行为是什么。当然,我已经添加了一个编辑示例。希望能有帮助。如果你觉得任何事情都可以更清晰地进行编辑,就可以进一步编辑。<代码>质量::分数(矩阵(1∶1,15,5,3))< /代码>?代替定义每个运算符的函数,你应该考虑使用分组,例如:代码>数学> /代码>组,用于所有的<代码> +,“-”,“*”,“/”,“^”,“%%”,“%/%”,和“,”“”,“!”","==", "!=", "“
。您定义了一个函数,该函数考虑了所有其他函数。有关更多信息,请查看数学information@Onyambu是的,说得好。我试图保持这一点的简单,但实际上,它仍然与Ops
定义中定义的通用操作一样清晰,所以我更新了它。我感谢您的反馈和宝贵的时间。@Allan Cameron:我没有注意到dims
(以及相关方法)在new\u vctrs
中被明确禁止的问题。这是一个遗憾,因为这感觉像是一个自然的延伸,但我相信这有很好的理由。无论如何,感谢您提供了一个框架来思考这个问题。@onyanbu感谢您对MASS::fracts
的建议。实际上,我对分数不感兴趣,但是,我只是有一个数据类型,它带有成对的条目,这会导致矩阵出现相同的问题,所以为了清楚起见,我想我会使用文档中的一个示例。更一般地说,我对vctrs
和矩阵之间的接口感兴趣。感谢您提供指向?Math
的有用指针。@MSR底层数据可以是矩阵格式,但不能是结果对象。这是实现和接口之间的区别,即后端和前端
x + 2
#> Error: <rational> + <double> is not permitted
#> Run `rlang::last_error()` to see where the error occurred.
x * 2
#> Error: <rational> * <double> is not permitted
#> Run `rlang::last_error()` to see where the error occurred.
x + x
#> Error: <rational> + <rational> is not permitted
#> Run `rlang::last_error()` to see where the error occurred.
`$.vctrs_rational` <- function(vec, symb) unclass(vec)[[as.character(symb)]]
is.rational <- function(num) class(num)[1] == "vctrs_rational"
gcd <- function(x, y) ifelse(x %% y, gcd(y, x %% y), y)
simplify <- function(num) {
common <- gcd(num$n, num$d)
rational(num$n / common, num$d/common)
}
x$n
#> [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
x$d
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
is.rational(x)
#> [1] TRUE
Ops.vctrs_rational <- function(vec, num)
{
if(!is.rational(vec)) {tmp <- vec; vec <- num; num <- tmp; }
if(.Generic == '*'){
if(is.rational(num)) return(simplify(rational(vec$n * num$n, vec$d * num$d)))
else return(simplify(rational(vec$n * 2, vec$d)))
}
else if (.Generic == '/'){
if(is.rational(num)) return(vec * rational(num$d, num$n))
else return(vec * rational(1, num))
}
else if (.Generic == '+'){
if(is.rational(num)){
new_n <- vec$n * (vec$d * num$d)/vec$d + num$n * (vec$d * num$d)/num$d
return(simplify(rational(new_n, vec$d * num$d)))
}
else return(simplify(rational(num * vec$d + vec$n, vec$d)))
}
else if (.Generic == '-'){
if(is.rational(num)) return(vec + rational(-num$n, num$d))
else return(vec + (-num))
}
else if (.Generic == '^'){
if(is.rational(num) | num < 0) stop("fractional and negative powers not supported")
return(simplify(rational(vec$n ^ num, vec$d ^ num)))
}
}
x * 3
#> <rational[15]>
#> [1] 3/1 3/2 1/1 3/4 3/5 1/2 3/7 3/8 1/3 3/10 3/11 1/4 3/13 3/14 1/5
x + x
#> <rational[15]>
#> [1] 2/1 1/1 2/3 1/2 2/5 1/3 2/7 1/4 2/9 1/5 2/11 1/6 2/13 1/7 2/15
(2 + x)^2 / (3 * x + 1)
#> <rational[15]>
#> [1] 3/1 25/8 49/15 27/8 121/35 169/48 25/7 289/80
#> [9] 361/99 147/40 529/143 625/168 243/65 841/224 961/255
as.vector.vctrs_rational <- function(x, ...) {
n <- x$n/x$d
attr(n, "denom") <- x$d
attr(n, "numerator") <- x$n
class(n) <- "rational_attr"
n
}
rational_matrix <- function(data, nrow = 1, ncol = 1,
byrow = FALSE, dimnames = NULL){
d <- as.vector(data)
m <- .Internal(matrix(d, nrow, ncol, byrow, dimnames, missing(nrow),
missing(ncol)))
m_dim <- dim(m)
attributes(m) <- attributes(d)
dim(m) <- rev(m_dim)
class(m) <- c("rational_matrix", "matrix")
m
}
format.rational_matrix <- function(x) {
return(paste0(attr(x, "numerator"), "/", attr(x, "denom")))
}
print.rational_matrix <- function(x)
{
print(matrix(format(x), nrow = dim(x)[2]), quote = FALSE)
}
matrix.default <- matrix
matrix <- function(data = NA, ...) UseMethod("matrix")
matrix.vctrs_rational <- function(data, ...) rational_matrix(data, ...)
matrix(x, nrow = 5)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 1/1 1/4 1/7 1/10 1/13
#> [2,] 1/2 1/5 1/8 1/11 1/14
#> [3,] 1/3 1/6 1/9 1/12 1/15
rational_matrix(x + 5, nrow = 3)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 6/1 21/4 36/7 51/10 66/13
#> [2,] 11/2 26/5 41/8 56/11 71/14
#> [3,] 16/3 31/6 46/9 61/12 76/15
rational_matrix(x + x, nrow = 5)
#> [,1] [,2] [,3]
#> [1,] 2/1 1/3 2/11
#> [2,] 1/1 2/7 1/6
#> [3,] 2/3 1/4 2/13
#> [4,] 1/2 2/9 1/7
#> [5,] 2/5 1/5 2/15