如何在Rcpp中按行写入列表中矩阵与稀疏矩阵的交错结果至文件?
Completing Rcpp Code to Write Interleaved Rows from Dense and Sparse Matrices
Here's a polished, functional version of your code that handles both dense matrix and sparse dgCMatrix objects, writes rows to a file in the interleaved order you specified, and includes error checking for robustness:
#include <RcppArmadillo.h> #include <fstream> #include <vector> // [[Rcpp::export]] bool write_rows(Rcpp::List data, Rcpp::CharacterVector clss, int n, std::string filename) { // Open output file std::ofstream outfile(filename); if (!outfile.is_open()) { Rcpp::Rcerr << "Error: Could not open file '" << filename << "' for writing." << std::endl; return false; } int num_objects = data.length(); // Validate input lengths match if (clss.length() != num_objects) { Rcpp::Rcerr << "Error: Length of 'clss' must match length of 'data'." << std::endl; outfile.close(); return false; } for (int row_idx = 0; row_idx < n; ++row_idx) { for (int obj_idx = 0; obj_idx < num_objects; ++obj_idx) { std::string current_class = Rcpp::as<std::string>(clss[obj_idx]); if (current_class == "matrix") { Rcpp::NumericMatrix mat = Rcpp::as<Rcpp::NumericMatrix>(data[obj_idx]); // Check if row index is within bounds if (row_idx >= mat.nrow()) { Rcpp::Rcerr << "Error: Row index " << row_idx << " exceeds rows in matrix at position " << obj_idx << "." << std::endl; outfile.close(); return false; } // Write dense row elements (comma-separated) Rcpp::NumericMatrix::Row row = mat.row(row_idx); for (int col_idx = 0; col_idx < row.size(); ++col_idx) { if (col_idx > 0) outfile << ","; outfile << row[col_idx]; } outfile << "\n"; } else if (current_class == "dgCMatrix") { arma::sp_mat sp_mat = Rcpp::as<arma::sp_mat>(data[obj_idx]); // Check if row index is within bounds if (row_idx >= sp_mat.n_rows) { Rcpp::Rcerr << "Error: Row index " << row_idx << " exceeds rows in dgCMatrix at position " << obj_idx << "." << std::endl; outfile.close(); return false; } // Convert sparse row to dense vector (preserves zeros) std::vector<double> row_data(sp_mat.n_cols, 0.0); arma::sp_mat::row_iterator it = sp_mat.begin_row(row_idx); arma::sp_mat::row_iterator it_end = sp_mat.end_row(row_idx); for (; it != it_end; ++it) { int col_pos = it.col(); row_data[col_pos] = *it; } // Write dense row elements (comma-separated) for (int col_idx = 0; col_idx < row_data.size(); ++col_idx) { if (col_idx > 0) outfile << ","; outfile << row_data[col_idx]; } outfile << "\n"; } else { Rcpp::Rcerr << "Error: Unsupported class '" << current_class << "' at position " << obj_idx << "." << std::endl; outfile.close(); return false; } } } // Cleanup and return success outfile.close(); return true; }
Key Improvements & Explanations:
- File Handling: Added a
filenameparameter and usesstd::ofstreamto safely open/write to files, with error checking for failed file openings. - Input Validation: Ensures the
clssvector length matches thedatalist length, and checks that row indices don't exceed the number of rows in each matrix. - Dense Matrix Handling: Directly extracts rows from
NumericMatrixand writes elements with a comma delimiter (easily changeable to space/tab if needed). - Sparse Matrix Handling: Converts
dgCMatrixto Armadillo'ssp_mat, then converts the sparse row to a dense vector to preserve zero values (matching dense matrix output format). - Error Reporting: Uses
Rcpp::Rcerrto print meaningful error messages to R's console, and cleans up the file handle before returning on failure.
Usage Example in R:
library(Rcpp) library(Matrix) # Compile the function sourceCpp("your_file_name.cpp") # Create sample data dense_mat <- matrix(rnorm(10), nrow = 5) sparse_mat <- Matrix(rnorm(10), nrow = 5, sparse = TRUE) data_list <- list(dense_mat, sparse_mat) class_list <- sapply(data_list, class) # Write rows to output.csv write_rows(data_list, class_list, 5, "output.csv")
This will write rows in the order: row 0 of dense matrix → row 0 of sparse matrix → row 1 of dense matrix → row 1 of sparse matrix, etc.
内容的提问来源于stack exchange,提问作者Daniel Falbel
相关产品推荐
相关产品推荐

