Skip to content

Commit

Permalink
Logical matrix and vector types, not mind MacOS
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwolaeth committed Jun 13, 2023
1 parent 56e63e9 commit 0b9e684
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 24 deletions.
40 changes: 20 additions & 20 deletions src/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

// Logical vectors and matrices — very useful
// Sometimes fails on Mac OS?
// typedef Eigen::Array<bool, Eigen::Dynamic, 1> VectorXl;
// typedef Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> MatrixXl;
typedef Eigen::Array<bool, Eigen::Dynamic, 1> VectorXl;
typedef Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> MatrixXl;

/*
TOMS462 is a C++ library which evaluates the upper right tail of the bivariate
Expand Down Expand Up @@ -66,24 +66,24 @@
const double pi = 3.1415926535; // set pi

// ## UTILS
Eigen::Array<bool, Eigen::Dynamic, 1> is_na(const Eigen::VectorXd& x) {
VectorXl is_na(const Eigen::VectorXd& x) {
return x.array().isNaN();
}

// Find pairwise complete observations for two vectors
Eigen::Array<bool, Eigen::Dynamic, 1> pairwise_complete(
VectorXl pairwise_complete(
const Eigen::VectorXd& x,
const Eigen::VectorXd& y
) {
Eigen::Array<bool, Eigen::Dynamic, 1> miss_x = x.array().isNaN();
Eigen::Array<bool, Eigen::Dynamic, 1> miss_y = y.array().isNaN();
VectorXl miss_x = x.array().isNaN();
VectorXl miss_y = y.array().isNaN();
return !(miss_x || miss_y);
}

// Filter vector based on the boolean mask
Eigen::VectorXd filter(
const Eigen::VectorXd& x,
const Eigen::Array<bool, Eigen::Dynamic, 1>& mask
const VectorXl& mask
) {
// Create empty vector to store selected values
Eigen::VectorXd xc = {};
Expand Down Expand Up @@ -121,10 +121,10 @@ Eigen::MatrixXd list_to_matrix(Rcpp::List lst) {
return mat;
}

Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> shadow_matrix(
MatrixXl shadow_matrix(
const Eigen::MatrixXd& M
) {
Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> shadow = !(M.array().isNaN());
MatrixXl shadow = !(M.array().isNaN());

return shadow.matrix();
}
Expand All @@ -140,7 +140,7 @@ int n_unique(const Eigen::VectorXd& x) {
}

// Overload n_unique with pre-defined filter mask
int n_unique(const Eigen::VectorXd& X, const Eigen::Array<bool, Eigen::Dynamic, 1>& keep) {
int n_unique(const Eigen::VectorXd& X, const VectorXl& keep) {
// Filter out NA values
Eigen::VectorXd x = filter(X, keep);

Expand Down Expand Up @@ -178,7 +178,7 @@ Eigen::VectorXd rank_(const Eigen::VectorXd& x) {
}

// Overload rank_ with pre-defined filter mask
Eigen::VectorXd rank_(const Eigen::VectorXd& v, const Eigen::Array<bool, Eigen::Dynamic, 1>& keep) {
Eigen::VectorXd rank_(const Eigen::VectorXd& v, const VectorXl& keep) {
// Filter out NA values
Eigen::VectorXd x = filter(v, keep);
int n = x.size();
Expand Down Expand Up @@ -426,7 +426,7 @@ double cor_pearson(const Eigen::VectorXd& x, const Eigen::VectorXd& y) {
// NaN-aware version to be used outside the main pipeline
double cor_pearson_safe(const Eigen::VectorXd& X, const Eigen::VectorXd& Y) {
// Filter for pairwise complete observations
Eigen::Array<bool, Eigen::Dynamic, 1> pco = pairwise_complete(X, Y);
VectorXl pco = pairwise_complete(X, Y);
Eigen::VectorXd x = filter(X, pco);
Eigen::VectorXd y = filter(Y, pco);

Expand All @@ -451,7 +451,7 @@ double cor_spearman(const Eigen::VectorXd& x, const Eigen::VectorXd& y) {
// NaN-aware version to be used outside the main pipeline
double cor_spearman_safe(const Eigen::VectorXd& X, const Eigen::VectorXd& Y) {
// Filter for pairwise complete observations
Eigen::Array<bool, Eigen::Dynamic, 1> pco = pairwise_complete(X, Y);
VectorXl pco = pairwise_complete(X, Y);
Eigen::VectorXd x = filter(X, pco);
Eigen::VectorXd y = filter(Y, pco);

Expand Down Expand Up @@ -625,7 +625,7 @@ Eigen::VectorXd estimate_thresholds(
// Overload estimate_thresholds with pre-defined filter mask
Eigen::VectorXd estimate_thresholds(
const Eigen::VectorXd& X,
const Eigen::Array<bool, Eigen::Dynamic, 1>& keep,
const VectorXl& keep,
const double& correct = 1e-08
) {
// Filter out NA values
Expand Down Expand Up @@ -789,7 +789,7 @@ double poly_xy(
) {
// Filter for pairwise complete observations
// auto start = std::chrono::system_clock::now(); // TIME IT
Eigen::Array<bool, Eigen::Dynamic, 1> pco = pairwise_complete(X, Y);
VectorXl pco = pairwise_complete(X, Y);
Eigen::VectorXd x = filter(X, pco);
Eigen::VectorXd y = filter(Y, pco);
// auto end = std::chrono::system_clock::now(); // TIME IT
Expand Down Expand Up @@ -848,7 +848,7 @@ double poly_xy_inside(
// Polychoric correlation given a numeric matrix
Eigen::MatrixXd poly_mat(
const Eigen::MatrixXd& X, // A numeric (integer) matrix
Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> shadow,
MatrixXl shadow,
Rcpp::List thresholds, // Pre-estimated thresholds
double correct = 1e-08 // Continuity correction value
) {
Expand All @@ -859,7 +859,7 @@ Eigen::MatrixXd poly_mat(
// Create item vectors and threshold templates
Eigen::VectorXd x(N), y(N), gamma, tau;
// Boolean vectors of whether an observation is not missing
Eigen::Array<bool, Eigen::Dynamic, 1> x_complete, y_complete;
VectorXl x_complete, y_complete;

// Check for discreteness
bool cont_x, cont_y;
Expand Down Expand Up @@ -907,7 +907,7 @@ Eigen::MatrixXd poly_df(Rcpp::List X, double correct = 1e-08) {
// Convert to matrix
Eigen::MatrixXd M = list_to_matrix(X);
// Cast a shadow of the data: a logical matrix to indicate non-missing entries
Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> shadow = shadow_matrix(M);
MatrixXl shadow = shadow_matrix(M);
// Create empty lists to store thresholds
Rcpp::List thresholds(m); // Estimate threshold values early
// Create threshold templates
Expand Down Expand Up @@ -1024,7 +1024,7 @@ Rcpp::List poly_df_full(Rcpp::List X, double correct = 1e-08) {
Eigen::MatrixXd M = list_to_matrix(X);
int N = M.rows(); // number of respondents
// Cast a shadow of the data: a logical matrix to indicate non-missing entries
Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> shadow = shadow_matrix(M);
MatrixXl shadow = shadow_matrix(M);
// Create empty lists to store thresholds
Rcpp::List thresholds(m); // Estimate threshold values early
// Create threshold templates
Expand Down Expand Up @@ -1175,7 +1175,7 @@ Polyserial optim_polyserial(
double correct = 1e-08
) {
// Filter and correct
Eigen::Array<bool, Eigen::Dynamic, 1> pco = pairwise_complete(X, D);
VectorXl pco = pairwise_complete(X, D);
Eigen::VectorXd x = filter(X, pco);
Eigen::VectorXd d = correct_data(filter(D, pco));

Expand Down
8 changes: 4 additions & 4 deletions tests/testthat/test-cor_polyserial.R
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ xm <- x
ym <- y
cm <- C
dm <- D
xm[sample(1:n, 13)] <- NaN
ym[sample(1:n, 13)] <- NaN
cm[sample(1:n, 13)] <- NA
dm[sample(1:n, 13)] <- NA
xm[sample(2:n, 13)] <- NaN
ym[sample(2:n, 13)] <- NaN
cm[sample(2:n, 13)] <- NA
dm[sample(2:n, 13)] <- NA

## TESTS ----
test_that("cor_polyserial() warns when finds zero values in an ordinal variable", {
Expand Down

0 comments on commit 0b9e684

Please sign in to comment.