有没有办法排除 C++ 数组中的行和列?
Is there a way to exclude rows and columns in a C++ array?
假设我有一个 C++ 数组,如下所示:
1 2 3 4 = arr
5 6 7 8
9 9 8 9
7 6 1 3
有没有一种简洁的方法可以排除任何行 and/or 列?
例如,假设我想对以下数组进行操作:
1 3 4
5 7 8
7 1 3
在其他编程语言中,我可以通过 arr[-3,-2] 排除第三行和第二列来相当容易地获得上述数组。但是,我一直找不到在 C++ 中排除行和列的简洁方法。你会怎么做?
更新:
我想这是一个 XY 问题。让我告诉你我为什么要这样做。
我是 运行 统计模型,特别是条件自回归 (CAR) 模型。在这个高斯模型中,我们需要均值函数和协方差矩阵。
我们得到均值函数为
mean = mu + Sig(i,-i) * inv(Sig(-i,-i)) * (v(i,-i) - mu)
协方差矩阵为
s2 = Sig(i,i) - Sig(i,-i) * inv(Sig(-i,-i)) * Sig(-i,i)
所以,我需要得到矩阵Sig的三个变体:Sig(l,-l), Sig(-l,-l), Sig(-l,l)。这就是为什么我希望找到一种简单的方法来排除行和列。我通常会在 R 中对此进行编程,但这需要很长时间。所以,我希望它能在 Rcpp 中运行。
下次更新:
我想我正在搞清楚,所以感谢评论者。这就是我的想法。我需要一个向量来存储我想保留在子矩阵中的索引。我计划使用 Rcpp 的 X.submat() 函数。
假设我想得到Sig的排除第i行第i列的子矩阵。然后我必须有一个包含 {0,1,...,(i-2),i,...,(L-1)} 的索引向量,因为 C++ 索引从 0 开始。要获得这个向量索引,我有以下代码:
// We need to get the vector of indices excluding i
arma::vec vece = arma::zeros(L-1); // vector to exclude the ith index
for(int k = 0; k < (L-1); k++){ // we have a vector of length L-1
if(k < (i-1)){
vece(k)=k;
}
else if(k == (i-1)){
// do not add the ith index
}
else{ // k > (i-1)
vece(k-1) = k;
}
}
// We need to make Sig(-i,-i)
arma::mat Sigee = arma::zeros(L-1,L-1); // ee for exclude,exclude
Sigee = Sig.submat(vece,vece)
但是,当 i = 0 时这似乎不起作用。我在以下 for 循环中有这段代码,所以我需要它在 i=0 时起作用。
for(int l = 0; l < L; l++){ }
对我来说,似乎更直接的方法是用连续整数填充 n-1
长度 uvec
,只是跳过 i
,就像这样:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
arma::mat exclude_one_row_and_col(const arma::mat& X, arma::uword i) {
arma::uword n = X.n_rows; // X should be square so only need # rows
arma::uvec idx(n-1); // vector of indices to subset by
arma::uword ii = 0; // the integer we'll add at each elem of idx
for ( arma::uword j = 0; j < (n-1); ++j ) { // for each elem of idx
if ( ii == i ) { // if ii equals i, we need to skip i
ii += 1; // (i.e., add 1 to ii)
}
idx[j] = ii; // then we store ii for this elem
ii += 1; // and increment ii
}
return X.submat(idx, idx); // finally we can subset the matrix
}
一个简单的演示表明它按预期工作:
X <- diag(1:3)
X
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 2 0
# [3,] 0 0 3
exclude_one_row_and_col(X, 0)
# [,1] [,2]
# [1,] 2 0
# [2,] 0 3
exclude_one_row_and_col(X, 1)
# [,1] [,2]
# [1,] 1 0
# [2,] 0 3
exclude_one_row_and_col(X, 2)
# [,1] [,2]
# [1,] 1 0
# [2,] 0 2
假设我有一个 C++ 数组,如下所示:
1 2 3 4 = arr
5 6 7 8
9 9 8 9
7 6 1 3
有没有一种简洁的方法可以排除任何行 and/or 列?
例如,假设我想对以下数组进行操作:
1 3 4
5 7 8
7 1 3
在其他编程语言中,我可以通过 arr[-3,-2] 排除第三行和第二列来相当容易地获得上述数组。但是,我一直找不到在 C++ 中排除行和列的简洁方法。你会怎么做?
更新:
我想这是一个 XY 问题。让我告诉你我为什么要这样做。
我是 运行 统计模型,特别是条件自回归 (CAR) 模型。在这个高斯模型中,我们需要均值函数和协方差矩阵。
我们得到均值函数为
mean = mu + Sig(i,-i) * inv(Sig(-i,-i)) * (v(i,-i) - mu)
协方差矩阵为
s2 = Sig(i,i) - Sig(i,-i) * inv(Sig(-i,-i)) * Sig(-i,i)
所以,我需要得到矩阵Sig的三个变体:Sig(l,-l), Sig(-l,-l), Sig(-l,l)。这就是为什么我希望找到一种简单的方法来排除行和列。我通常会在 R 中对此进行编程,但这需要很长时间。所以,我希望它能在 Rcpp 中运行。
下次更新:
我想我正在搞清楚,所以感谢评论者。这就是我的想法。我需要一个向量来存储我想保留在子矩阵中的索引。我计划使用 Rcpp 的 X.submat() 函数。
假设我想得到Sig的排除第i行第i列的子矩阵。然后我必须有一个包含 {0,1,...,(i-2),i,...,(L-1)} 的索引向量,因为 C++ 索引从 0 开始。要获得这个向量索引,我有以下代码:
// We need to get the vector of indices excluding i
arma::vec vece = arma::zeros(L-1); // vector to exclude the ith index
for(int k = 0; k < (L-1); k++){ // we have a vector of length L-1
if(k < (i-1)){
vece(k)=k;
}
else if(k == (i-1)){
// do not add the ith index
}
else{ // k > (i-1)
vece(k-1) = k;
}
}
// We need to make Sig(-i,-i)
arma::mat Sigee = arma::zeros(L-1,L-1); // ee for exclude,exclude
Sigee = Sig.submat(vece,vece)
但是,当 i = 0 时这似乎不起作用。我在以下 for 循环中有这段代码,所以我需要它在 i=0 时起作用。
for(int l = 0; l < L; l++){ }
对我来说,似乎更直接的方法是用连续整数填充 n-1
长度 uvec
,只是跳过 i
,就像这样:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
arma::mat exclude_one_row_and_col(const arma::mat& X, arma::uword i) {
arma::uword n = X.n_rows; // X should be square so only need # rows
arma::uvec idx(n-1); // vector of indices to subset by
arma::uword ii = 0; // the integer we'll add at each elem of idx
for ( arma::uword j = 0; j < (n-1); ++j ) { // for each elem of idx
if ( ii == i ) { // if ii equals i, we need to skip i
ii += 1; // (i.e., add 1 to ii)
}
idx[j] = ii; // then we store ii for this elem
ii += 1; // and increment ii
}
return X.submat(idx, idx); // finally we can subset the matrix
}
一个简单的演示表明它按预期工作:
X <- diag(1:3)
X
# [,1] [,2] [,3]
# [1,] 1 0 0
# [2,] 0 2 0
# [3,] 0 0 3
exclude_one_row_and_col(X, 0)
# [,1] [,2]
# [1,] 2 0
# [2,] 0 3
exclude_one_row_and_col(X, 1)
# [,1] [,2]
# [1,] 1 0
# [2,] 0 3
exclude_one_row_and_col(X, 2)
# [,1] [,2]
# [1,] 1 0
# [2,] 0 2