给还没有预处理出数据的同学一点点帮助,大神勿喷^^
B题的题目以及数据集就不贴了,网上都可以下载的到的。
问题一、请用适当的方法,把genotype.dat中每个位点的碱基(A,T,C,G) 编码方式转化成数值编码方式,便于进行数据分析。
第一问其实是一个铺垫,目的是方便后面三问的数据处理的方便,所以第一问要将ATCG四个碱基的编码转换成容易让计算机处理和分析的数值编码方式。
思路:
- 例如第一个位点是用CT编码的,1000个样本中每个位点也就只有三种组合方式——CC,CT,TT。有的同学可能会有疑问,CT和TC一样吗?其实是一样的,题目中已经说明了。那么,我们可以将其分别编码为0,1,2(碱基一样的是偶数,碱基不同的是奇数)。
- 这样编码的话,那么问题来了:比如CT组成的位点我们编码为CC(0),CT(1),TT(2)。CG组成的位点我们同理编码为CC(0),CG(1),GG(2),这时还是OK的,再来一对TG编码TT(0),TG(1),GG(2)。这个时候TT(0)和上面的TT(2)就冲突了。刚开始的想法是为碱基对的所有可能组合进行不同的编码,但是觉得引入过多数据不易于处理,就放弃了。
- 我这里是采用记录每个位点的碱基对存入一个vector<string>容器中来解决的。并且在记录碱基对的时候,已经将单个碱基对进行了字典序排列(TC->CT),方便后面转换编码方式。碱基对的两个字母相同的情况下:字典序小的是0,字典序大的是2,其他是1。具体分析数据的时候,再将位点中对应的碱基对调出来对比一下。
- 当然,大家也可以用自己的思路进行编码,源码框架已经给出,可以自行修改。
数据的导入与输出头文件RDWR.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#ifndef RDWR_H #define RDWR_H #include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> using namespace std; //template<typename T> vector<vector<string>> dataRead(string FilePath, int row, int col) { ifstream input(FilePath); if (!input.is_open()){ cerr << "File is not existing, check the path: \n" << FilePath << endl; exit(1); } vector<vector<string>> RS(row, vector<string>(col, " ")); string line; //按行读取文件中的数据 getline(input, line); //第一行位点名,不处理 for (int i = 0; i < row; ++i){ getline(input, line); istringstream record(line); //将每行数据保存在istringstream流中 for (int j = 0; j < col; ++j) record >> RS[i][j]; } return RS; } template<typename T> void dataWrite(vector<vector<T>> Matrix, string dest) { ofstream output(dest); vector<vector<T>>::size_type row = Matrix.size(); vector<vector<T>>::size_type col = Matrix[0].size(); for (unsigned i = 0; i<row; ++i){ for (unsigned j = 0; j<col; ++j) output << Matrix[i][j] << '\t'; output << endl; } } #endif |
将碱基对转换成数字编码头文件letter_to_number.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include <iostream> #include <string> #include <vector> #include <algorithm> using namespace std; //将每个位点中的两个碱基统计出来,并按字典序重排,然后将每个位点涉及的两个碱基放入容器中 vector<string> isATCG(vector < vector<string> >Matrix) { vector<vector<string>>::size_type row = Matrix.size(); vector<vector<string>>::size_type col = Matrix[0].size(); vector<string> atcg; for (vector<vector<string>>::size_type j = 0; j < col; ++j){ for (vector<vector<string>>::size_type i = 0; i < row; ++i){ if (Matrix[i][j][0] != Matrix[i][j][1]){ sort(Matrix[i][j].begin(), Matrix[i][j].end()); atcg.push_back(Matrix[i][j]); break; } else continue; } } //打印输出位点包含碱基对的信息 cout << " 所有位点包含如下碱基对: " << endl; for (auto iter = atcg.begin(); iter != atcg.end(); ++iter) cout << *iter << '\t'; return atcg; } vector<vector<int>> letterToNumber(vector<vector<string>> Matrix, int row, int col) { vector<vector<int>> numberMatrix(row, vector<int>(col, 0)); vector<string> atcg = isATCG(Matrix); for (auto j = 0; j < col; ++j){ for (auto i = 0; i < row; ++i){ string letters = atcg[j]; if (Matrix[i][j] == letters.substr(0,1)+letters.substr(0,1) ) numberMatrix[i][j] = 0; else if (Matrix[i][j] == letters.substr(1, 1) + letters.substr(1, 1)) numberMatrix[i][j] = 2; else numberMatrix[i][j] = 1; } } return numberMatrix; } |
下面是主函数main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "RDWR.h" #include "letter_to_number.h" #include <iostream> #include <vector> using namespace std; int main() { string FilePath1("E:\\essential c++\\数学建模B卷\\data\\genotype.dat"); string FilePath2("E:\\essential c++\\数学建模B卷\\data\\cleaned_genotype.dat"); int row = 1000; //建议电脑性能一般的同学在实验的时候先选取较小的维度 int col = 9445; //进行测试,否则可能会跑好久,我的本本跑的很吃力 vector<vector<string>> RS = dataRead(FilePath1, row, col); vector<vector<int>> numberRS = letterToNumber(RS, row, col); dataWrite(numberRS, FilePath2); system("pause"); return 0; } |
数据预处理结果:
写的比较仓促,再加上技术有限,复杂度较高,有兴趣的同学可以自行优化。如有错误请留言指出,共同讨论。
你好,能不能分析一下B题第三问和第四问的思路啊?