在下面的C++代码中增加一个功能具体为:以矩阵中列名为group的这一列分组然后计算每一组的mic系数最后分别输出#include cstdlib#include cmath#include iostream#include fstream#include sstream#include vector#include cppmineh#include boostalgorithmstringhpp
在给定的C++代码中,可以通过以下步骤增加一个功能以实现对矩阵中名为"group"的列进行分组,并计算每组的mic系数:
-
在read_tsv函数中,添加一个额外的参数,用于存储分组列的索引。例如,可以将该参数命名为"group_index"并将其设置为默认值-1。
-
在read_tsv函数中,读取第一行并解析为列名后,找到名为"group"的列的索引,并将其存储在"group_index"参数中。
-
在calc_mic函数中,根据"group_index"参数将矩阵的列分组。
-
创建一个map对象,用于存储每个组的mic系数。键为组的名称,值为mic系数。
-
在calc_mic函数的内部循环中,根据当前的组名称将mic系数存储到map对象中。
-
在write_tsv函数中,根据map对象中的mic系数输出每个组的mic系数。
下面是修改后的代码:
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include "cppmine.h"
#include <boost/algorithm/string.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/program_options.hpp>
#include <iomanip>
#include <omp.h>
namespace po = boost::program_options;
using namespace boost::numeric::ublas;
// 读取文件
matrix<double, row_major> read_tsv(const std::string& filename, std::vector<std::string>& col_names, int& group_index) {
std::ifstream in(filename);
std::string line;
std::vector<std::vector<double>> data;
// 读取第一行并解析为列名
if (std::getline(in, line)) {
boost::algorithm::split(col_names, line, boost::is_any_of("\t"));
col_names.erase(col_names.begin(), col_names.begin() + 1); // 去除第一个空列
// 查找名为"group"的列索引
for (size_t i = 0; i < col_names.size(); ++i) {
if (col_names[i] == "group") {
group_index = i;
break;
}
}
}
while (std::getline(in, line)) {
std::vector<std::string> str_vec;
boost::algorithm::split(str_vec, line, boost::is_any_of("\t"));
std::vector<double> num_vec(str_vec.size() - 1);
std::transform(str_vec.begin() + 1, str_vec.end(), num_vec.begin(),
[](const std::string& str) { return std::stod(str); });
data.push_back(num_vec);
}
matrix<double, row_major> mat(data.size(), data[0].size());
for (size_t i = 0; i < mat.size1(); ++i)
for (size_t j = 0; j < mat.size2(); ++j)
mat(i, j) = data[i][j];
return mat;
}
//计算mic系数
std::map<std::string, double> calc_mic(const matrix<double, row_major>& mat, int threads, int group_index) {
// 当样本量小于6个时,终止程序
if (mat.size1() < 6) {
std::cerr << "error: the number of data rows should be greater than 5." << std::endl;
}
if (mat.size2() < 2) {
std::cerr << "error: the number of data columns should be greater than 1." << std::endl;
}
// 创建空的对称矩阵
matrix<double, row_major> result(mat.size2(), mat.size2());
// 创建MINE对象
MINE mine(0.5, 15, EST_MIC_APPROX);
// 创建map对象,用于存储每个组的mic系数
std::map<std::string, double> mic_map;
// 计算每列两两之间的mic系数,并填充对称矩阵
omp_set_num_threads(threads);
#pragma omp parallel for
for (size_t i = 0; i < mat.size2(); i++) {
for (size_t j = i + 1; j < mat.size2(); j++) { // 计算上三角部分
double x[mat.size1()];
double y[mat.size1()];
for (size_t k = 0; k < mat.size1(); k++) {
x[k] = mat(k, i);
y[k] = mat(k, j);
}
mine.compute_score(x, y, mat.size1());
result(i, j) = mine.mic();
result(j, i) = result(i, j); // 填充下三角部分
// 根据当前的组名称将mic系数存储到map对象中
std::string group_name = col_names[group_index];
mic_map[group_name] = mine.mic();
}
}
return mic_map;
}
//导出结果
void write_tsv(const std::string& filename, const std::map<std::string, double>& mic_map) {
std::ofstream out(filename);
// 输出列名
out << "Group\tMIC\n";
// 输出每个组的mic系数
for (const auto& pair : mic_map) {
out << pair.first << "\t" << std::setprecision(3) << std::fixed << pair.second << "\n";
}
}
//main函数
int main(int argc, char** argv) {
// 声明命令行参数选项
int default_threads = 4;
int threads;
po::options_description desc(" Multi-threaded computation of maximum information coefficient.\n"
" For more detailed information, please refer to https://minepy.readthedocs.io/en/latest/");
desc.add_options()
("help,h", "help message")
("input,i", po::value<std::string>(), "input.txt")
("output,o", po::value<std::string>(), "output.txt,The first column is the name of the indicator, such as ASV/OTU or gene")
("threads,t", po::value<int>(&threads)->default_value(default_threads), "number of threads (default 4)");
// 解析命令行参数选项
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << "\n";
return 0;
}
if (vm.empty()) {
std::cout << desc << "\n";
return 0;
}
int coreNum = omp_get_num_procs(); // 获得处理器个数
if (coreNum > 1 && threads > coreNum) {
fprintf(stderr, "\n%s: error: only %d threads are available\n", argv[0], coreNum);
exit(1);
}
if (vm.count("input")) {
std::string filename = vm["input"].as<std::string>();
std::ifstream file(filename);
if (file) {
// 文件存在,执行你的操作
if (vm.count("output")) {
std::vector<std::string> col_names;
int group_index = -1;
auto mat = read_tsv(vm["input"].as<std::string>(), col_names, group_index);
auto mic_map = calc_mic(mat, threads, group_index);
write_tsv(vm["output"].as<std::string>(), mic_map);
} else {
std::cerr << "output is not specified!" << std::endl;
return 1;
}
} else {
// 文件不存在
std::cerr << vm["input"].as<std::string>() << " not found!" << std::endl;
return 1;
}
} else {
std::cerr << "No file provided!" << std::endl;
return 1;
}
return 0;
}
在修改后的代码中,增加了一个名为"group_index"的参数来存储分组列的索引。在read_tsv函数中,找到名为"group"的列索引并将其存储在"group_index"参数中。在calc_mic函数中,根据"group_index"参数将矩阵的列分组,并根据当前的组名称将mic系数存储到map对象中。最后,在write_tsv函数中,根据map对象中的mic系数输出每个组的mic系数。
原文地址: https://www.cveoy.top/t/topic/ipHi 著作权归作者所有。请勿转载和采集!