如何使用R从矩阵L中删除对角元素(diagL)?我尝试使用以下内容:
subset(L, select=-diag(L)) or
subset(L, select=-c(diag(L)))
但我得到0个数字......
答案 0 :(得分:14)
R编程语言?我更喜欢C,拼写更容易。
一种方法是按照我喜欢的方式创建一个带有数字的矩阵:
a<-t(matrix(1:16,nrow=4,ncol=4))
看起来像:
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
删除对角线上的值:
diag(a)=NA
导致:
[,1] [,2] [,3] [,4]
[1,] NA 2 3 4
[2,] 5 NA 7 8
[3,] 9 10 NA 12
[4,] 13 14 15 NA
要实际删除这些值,而不是让它们消失,我们需要重新制作:
a<-t(matrix(t(a)[which(!is.na(a))],nrow=3,ncol=4))
结果是:
[,1] [,2] [,3]
[1,] 2 3 4
[2,] 5 7 8
[3,] 9 10 12
[4,] 13 14 15
这与我们在上面的C中得到的相同。
这有点迂回但它导致了我认为正确的答案。我有兴趣看到一个比我更了解R的人改进的解决方案。
对作业的一些解释:
a<-t(matrix(t(a)[which(!is.na(a))],nrow=3,ncol=4))
!is.na(a)
为我们提供了一个TRUE,FALSE值列表,其中的元素已被清除。which(!is.na(a))
为我们提供了每个真元素的下标列表。t(a)
转换矩阵,因为我们需要根据#2中的下标来提取矩阵。t(a)[which(!is.na(a))]
为我们提供了一个缺少对角线NA值的数字列表。matrix(t(a)[which(!is.na(a))],nrow=3,ncol=4)
将#4中的列表转换为矩阵,这是我们想要的转置。a<-t(matrix(1:16,nrow=4,ncol=4))
(整件事)将#5转换为我们想要的形式,并将其分配给a
变量。这适用于a<-t(matrix(11:26,nrow=4,ncol=4))
。
答案 1 :(得分:7)
以下是一些人工数据:
x <- matrix(1:16, 4, 4)
n <- nrow(x)
x
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
在对矩阵x
进行矢量化之后,对角线元素对应于索引1, n+2, 2*n+3, ...
,即对应于序列seq(1, n^2, n+1)
。您可以通过
x[-seq(1,n^2,n+1)]
[1] 2 3 4 5 7 8 9 10 12 13 14 15
&#34>删除对角线&#34;对于矩阵,您可以向上移动下三角矩阵以获得具有n-1
行和n
列的矩阵
matrix(x[-seq(1,n^2,n+1)], n-1, n)
[,1] [,2] [,3] [,4]
[1,] 2 5 9 13
[2,] 3 7 10 14
[3,] 4 8 12 15
或者,这可能是您想要的,您可以将下三角矩阵向右移动以通过在移除之前转置n
来获得包含n-1
行和x
列的矩阵对角线指数并将其转换回来
t(matrix(t(x)[-seq(1,n^2,n+1)], n-1, n))
[,1] [,2] [,3]
[1,] 5 9 13
[2,] 2 10 14
[3,] 3 7 15
[4,] 4 8 12
答案 2 :(得分:2)
请记住,对角线将具有相同的X和Y索引。将C中的对角线归零的快速程序如下:
#include <stdio.h>
static void printMat(char mat[4][4], char *comment)
{
printf("%s:\n", comment);
for(int jj=0; jj<4; jj++) {
for(int ii=0; ii<4; ii++) {
printf("%2d ",mat[jj][ii]);
}
printf("\n");
}
}
main()
{
static char matrix[4][4]= {
{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9,10,11,12},
{13,14,15,16}
};
printMat(matrix,"Before");
for(int ii=0; ii<4; ii++) {
matrix[ii][ii]=0;
}
printMat(matrix,"After");
}
这导致:
Before:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
After:
0 2 3 4
5 0 7 8
9 10 0 12
13 14 15 0
要删除,只需清除对角线就更复杂了。
这应该可以解决这个问题:(请记住,零字节的memcpy可以解决那些不存在的元素。)
#include <stdio.h>
#include <strings.h>
static void printMat(char *mat, int xDim, int yDim,char *comment)
{
printf("%s:\n", comment);
for(int jj=0; jj<yDim; jj++) {
for(int ii=0; ii<xDim; ii++) {
printf("%2d ",(mat[(jj)*xDim+ii]) );
}
printf("\n");
}
}
main()
{
static char matrix[4][4]= {
{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9,10,11,12},
{13,14,15,16}
};
static char new[4][3];
printMat((char*)matrix,4,4,"Before");
for(int ii=0; ii<4; ii++) {
memcpy(&new[ii][0], &matrix[ii][0],ii);
memcpy(&new[ii][ii],&matrix[ii][ii+1], 4-ii);
}
printMat((char*)new,3,4,"After");
}
结果:
Before:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
After:
2 3 4
5 7 8
9 10 12
13 14 15
当然,如果你想要其他语言的东西,可以提问。
答案 3 :(得分:0)
仍然使用基本R,可以组合使用upper.tri()
和lower.tri
在一行中查找所需内容。为了更方便,我创建了一个单行函数。代码如下。
a <- matrix(rnorm(100), nrow = 4, ncol = 4)
select_all_but_diag <- function(x) matrix(x[lower.tri(x, diag = F) | upper.tri(x, diag = F)], nrow = nrow(x) - 1, ncol = ncol(x))
select_all_but_diag(a)
这是矩阵a
(在我的情况下):
[,1] [,2] [,3] [,4]
[1,] 0.3 2.5 -0.5 2.8
[2,] 0.7 1.1 -1.4 -0.7
[3,] 0.9 0.8 1.6 0.5
[4,] -0.8 -0.3 -0.9 1.6
这是select_all_but_diag(a)
输出矩阵:
[,1] [,2] [,3] [,4]
[1,] 0.7 2.5 -0.5 2.8
[2,] 0.9 0.8 -1.4 -0.7
[3,] -0.8 -0.3 -0.9 0.5
编辑主要行
相反,如果您希望折叠是行主要的,则可以使用此功能的扩展版本,该功能使您可以折叠矩阵,从而减少列数而不是行数。
select_all_but_diag <- function(x, collapse_by = "row") {
if(collapse_by == "row") matrix(x[lower.tri(x, diag = F) | upper.tri(x, diag = F)], nrow = nrow(x) - 1, ncol = ncol(x))
else if(collapse_by == "col") t(matrix(t(x)[lower.tri(x, diag = F) | upper.tri(x, diag = F)], nrow = nrow(x) - 1, ncol = ncol(x)))
else stop("collapse_by accepts only 'row' or 'col'.")
}
a
select_all_but_diag(a, collapse_by = "col")
这是后者的输出:
[,1] [,2] [,3]
[1,] 2.5 -0.5 2.8
[2,] 0.7 -1.4 -0.7
[3,] 0.9 0.8 0.5
[4,] -0.8 -0.3 -0.9