如何解决在C ++中找到向量中每个索引处累积的唯一元素计数的有效方法
所以我有一个基因比对结果(我认为是来自RNA-seq),其中特定的序列与某些基因相匹配(这些基因有时会自我重复)。现在,我正在使用C ++查找最早的位置,在该位置可以对大多数独特基因进行计数,因此我可以放心地仅使用第一部分进行进一步分析。问题是我拥有的文件已排序(因此,来自同一基因的序列被放在一起),但是我想对未排序的文件进行计算。
我现在正在做的是手动std::shuffle
我的std::vector<string> geneList
,然后再遍历它。在每次迭代中,我都会将geneList中的每个即将来临的基因与唯一的基因列表进行比较,如果其中一个都不匹配该即将来临的基因,则会对其进行更新。然后,我将以一定的间隔对count_gene和count_unique_gene进行采样,并最终获得x%的位置。这是非常昂贵的……只有14万个基因花了我几分钟时间。示例代码(还包括我的输入代码以更好地理解):
#include <stdlib.h>
#include <stdint.h>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <fstream>
#include <sstream>
#include <random>
#include <algorithm>
class COUNT{
public:
// COUNT() : sampRate(1) {};
// ~COUNT(){};
void initialize();
void readData();
void calcCount();
void writeCount();
private:
int sampRate;
int countRead;
int countUniqGene;
string fname;
vector<string> geneList;
vector<int> sampCountRead,sampCountUniqGene;
};
void COUNT::readData(){
std::cout<<"Type in fname: "<<endl;
// std::cin>>fname;
fname = "testdata.sam";
std::cout<<"Type in sample rate: "<<endl;
std::cin>>sampRate;
std::string line;
std::fstream readFile(fname);
while (getline(readFile,line)) {
if (((char)line.back() == '-') | ((char)line.back() == '+')) {
std::istringstream ss(line);
std::string others,oriGeneName,realGeneName;
ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others;
if (ss >> others) {
ss >> oriGeneName;
realGeneName = oriGeneName.substr(5,oriGeneName.size());
geneList.push_back(realGeneName);
}
else continue;
}
else continue;
}
readFile.close();
}
void COUNT::calcCount() {
set<string> uniqGeneList = {"test"};
auto rng = std::default_random_engine{};
std::shuffle(std::begin(geneList),std::end(geneList),rng); // this is fast (0.02s)
vector<string>::iterator uniqIter;
string geneName;
for (vector<string>::iterator iter = geneList.begin(); iter != geneList.end(); ++iter) { //this is very slow
geneName = string(iter[0]);
if (all_of(uniqGeneList.begin(),uniqGeneList.end(),[geneName](const std::string gene) {return geneName != gene; })) {
uniqGeneList.insert(geneName);
countUniqGene++;
}
countRead++;
if (countRead % sampRate < 1) {
sampCountRead.push_back(countRead);
sampCountUniqGene.push_back(countUniqGene);
}
}
}
int main(){
(not important,plotting and intersecting)
}
也有样本数据(我从'GE:Z:
V300067289_HH26L1C001R0010008289 784 7 141178046 3 2S48M * 0 0 CCCCACCTGCTTGCGGACCCTAATGTGACGTTGGCGGATGAGCACACGGG F)BF;E2A3*F<+AFFB-B,FE?FEFFF@EF3BFB;<:FECEF2DFF@CE NH:i:2 HI:i:1 AS:i:47 nM:i:0 CB:Z:53_34_81098_51183 UR:Z:GTTTTATTA UY:Z:E/E@EAG?F
V300067289_HH26L1C001R0010008294 1040 3 34078775 255 50M * 0 0 CCTTGTCTGGGTGATTTAATAGCATAATCCGGCGATGAGCATCCCTGATC FGFBGFFFDEGEBFEFBDFEEFFGCFFFADEEFGFFFFGFGFFDFFEEFF NH:i:1 HI:i:1 AS:i:49 nM:i:0 CB:Z:49_31_75043_46832 UR:Z:CCGGACCCA UY:Z:EEEfdbFEA XF:Z:CODING GE:Z:Dnajc19 GS:Z:-
V300067289_HH26L1C001R0010008295 1040 3 34078777 255 2S48M * 0 0 CGTTGTCTGGGTGATTTAATACCAAAATCCGGCGATGAGCATCCCTGATC E(FC6D>+EDEFECA?@?:C.'D4&03@&;:3?7CFAEF@C7A4.4.@B? NH:i:1 HI:i:1 AS:i:43 nM:i:2 CB:Z:49_31_75043_46832 UR:Z:CCGGACCCA UY:Z:CFFD?EEDF XF:Z:CODING GE:Z:Dnajc19 GS:Z:-
V300067289_HH26L1C001R0010008298 1040 15 82351046 255 50M * 0 0 ACTTTATCCCGTCCTTGTTTCACCGTGATATCCAGCTGCATTAAGTGCAC )EFFF=FE?DC=FABGFFF7F&=FEF9FBEE=BEB9FFF;FFCF9DBF86 NH:i:1 HI:i:1 AS:i:49 nM:i:0 CB:Z:49_34_74093_51329 UR:Z:CAATATAGG UY:Z:DFFFFFFFF XF:Z:CODING GE:Z:Ndufa6 GS:Z:-
我曾经考虑过假设基因的出现遵循泊松分布,只计算唯一的基因数目并计算每个位置达到x%的置信度。但是最好先使用模拟。预先感谢!
解决方法
set<string> uniqGeneList = {"test"};
std::set
的全部目的是能够快速(如对数复杂度)检查是否存在特定值,无论该值是否存在于集合中。
if (all_of(uniqGeneList.begin(),uniqGeneList.end(),[geneName](const std::string gene) {return geneName != gene; })) {
因此,与其让std::set
确切地说明其存在的唯一目的,也不是因为发明它的唯一原因,而是最终手动遍历集合中的每个值,并手动比较它?正如Spock先生所说:这是不合逻辑的。
这整个事情必须简单地替换为:
if (uniqGeneList.find(geneName) == uniqGeneList.end()) {
粗略估计:集合中包含约1,000个值,最终将结果以八种取代一千种。通过将std::set
替换为std::unordered_set
,也可以实现一些进一步的性能提升。您将需要对此进行概要分析,以查看这是否是用例的结果。
其他一些值得注意的事情:
std::istringstream ss(line);
std::string others,oriGeneName,realGeneName;
ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others; ss >> others;
流以低效而著称。这也可能是牺牲太多电子的另一部分。在对性能敏感的情况下,抛开std::istringstream
,卷起袖子,遍历整个行,数词时要多加注意,这也可能会降低性能。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。