数据集处理

来源:互联网 发布:11年体测数据 编辑:程序博客网 时间:2024/06/07 14:34

读入形如:

1 all:148 anger:22 disgust:2 fear:60 joy:0 sad:64 surprise:0mortar assault leav at least dead

2 all:131 anger:0 disgust:0 fear:0 joy:93 sad:0 surprise:38goal delight for sheva

这样的文本,得到OneHot,TF,TF-IDF矩阵,以及利用三元组去替代0-1矩阵表示数据。

算法原理:

  因为需要去重且不排序,C++中并没有这样的数据结构来存储,因此按照数据集中的字符串出现的顺序,用一个map<string,int>去存储,int值存储这个字符串第一次出现的下标,再维护一个map<int,int>RepeatTimes,first为出现的下标,second为在数据集中出现的次数,再维护一个map<int,int>AppearLinesfirst存储下标,second存储的是对应下标的字符串出现过的行数,读入文件过程中维护整型变量数据的行数Lines,不同的字符串的个数Index,这样就可以得到一个二维矩阵。并且每次都用一个结构体Three_Var存储一个字符串对应的行数i,列数j,以及出现过的行数v,并放入Three_var类型的vector容器中。

OneHot: 遍历的是一个矩阵,如果行数和列数和当前vector中的Three_Var中的i,j分别相等,则写入1,否则写入0

TF:OneHot进行归一化即可。因此需要在读取文件的过程中用一个名为NumsOfLines

vector记录每一行的单词的个数。

TF-IDF:按照公式计算即可,因为我们在读取文件时维护了每个下标对应的字符串出现

过的行数AppearLines,所以只需计算即可。

Smatrix1:通过LinesIndex遍历矩阵,如果行数和列数和当前vector中的Three_Var中的i,j分别相等,则得到一个三元组,写入smatrix1.

遍历完每一行进行换行即可得到对应的矩阵。


#include<iostream>

#include<fstream>
#include<map>
#include<vector> 
#include<sstream>
#include<cmath>
using namespace std;
struct Three_Var
{
int i,j,v;
bool operator<(Three_Var& t) {return i<t.i||(i==t.i&&j<t.i);}
bool operator==(Three_Var& t) {return i==t.i&&j==t.j;}
};
int main()
{
int index=0;//依次出现的(去重)词汇的对应下标 
int Lines=0;//出现的行数 
int ThreeVarNums=0;//三元组的个数 
ifstream Input;
Input.open("semeval");//读取文件 
string line; //一个临时变量而已 
map<string, int> FirstIndex;//string是对应的词汇,int是它(无视重复下)第一次出现的在该map中的下标 
map<int, int> RepeatTimes,AppearLines;//default key ascending in map
vector<int> NumsOfLines;//每行的词汇个数 (重复不算1个)
vector<Three_Var> smat;
while(getline(Input,line))
{
stringstream ss;
int temp;
//几经周折注意到一个事实:用写字板或者dev_cpp打开时可以清楚地看见是一行一句话的,所以用stringstream
//整行读入的特性会方便很多 
ss.clear(); 
ss.str(line);//From:http://blog.csdn.net/lanbing510/article/details/42423333
//str()成员函数的使用可以让istringstream对象返回一个string字符串 
ss>>temp;    //读入一个整数,也就是每行的序号 
string dict; 
for(int i=0;i<7;i++)//因为有all,anger,disgust,fear,joy,sad,surprise七项,所以循环7次 
ss>>dict;
temp=0;
map<string,int>::iterator it1;
map<int,int>::iterator it2;
map<int,int>::iterator it3;
RepeatTimes.clear();
while(ss>>dict)  //读入每行的数据集内容的词汇 
{
it1=FirstIndex.find(dict); //first元素的map查找函数 
if(it1==FirstIndex.end())//迭代器到了end(),说明这个词还没出现过 
{
FirstIndex.insert(pair<string,int>(dict,index));
index++;  //维护map中的下标 
}
it2=RepeatTimes.find(FirstIndex[dict]);//计算该词汇在数据集中重复出现的次数 
if(it2==RepeatTimes.end())//这个下标第一次出现的话,放进这个repaeatTimes<int,int>中 
RepeatTimes.insert(pair<int,int>(FirstIndex[dict],1));
//第一个整数记录它在map中的下标,第二个整数记录它重复的次数 
else
it2->second++;//否则,维护好这个RepeatTimes即可。 
temp++;//这行的词汇个数(重复不算1个) 
}
//读取完这行词汇了 

for(it2=RepeatTimes.begin();it2!=RepeatTimes.end();it2++)
{
it3=AppearLines.find(it2->first);//每个词汇对应的下标重复的次数 
//计算在所有数据集中出现的次数 
if(it3==AppearLines.end()) //如果是空的,说明第一次出现 
AppearLines.insert(pair<int,int>(it2->first,1));
else
it3->second++; //it3的second存储的是对应下标的字符串出现的行数 
Three_Var item{Lines,it2->first,it2->second};
//利用机构体记录这个单词出现的行数,下标,重复次数 
smat.push_back(item);
ThreeVarNums++;//结构体vector中放入的个数 
}
Lines++;  //第几行计数 
NumsOfLines.push_back(temp);//记录好每行的词汇个数 
}
Input.close();
//读取完整个文档 

//接下来进行处理数据 
ofstream OneHot,TF,TF_IDF,SMATRIX1;
OneHot.open("OneHot");
TF.open("TF");
TF_IDF.open("TFIDF");
SMATRIX1.open("smatrix1"); //三元组矩阵 
SMATRIX1<<Lines<<endl<<index<<endl<<ThreeVarNums<<endl;
int pos=0;
for(int i=0;i<Lines;i++) //行数 
{
/*————————每一行的处理————————*/ 
for(int j=0;j<index;j++) //字符串下标 
{
if(smat[pos].i==i&&smat[pos].j==j)  //匹配到一个字符串出现 
{
OneHot<<1<<" ";      //OneHot矩阵为1 
double rate=(double)smat[pos].v/NumsOfLines[i];  //归一化频率 
TF<<rate<<" "; 
TF_IDF<<rate*log((double)Lines/(1+AppearLines[j]))<<" "; //TF-IDF矩阵 
SMATRIX1<<i<<" "<<j<<" "<<1<<endl;//输出到三元组 
if(smat[pos].i>=Lines/2)
smat[pos].i-=Lines/2;
pos++;//找下一个字符串了 
}
else
{
OneHot<<0<<" ";       //不出现,这3个矩阵都是0,三元组则例外 
TF<<0<<" ";
TF_IDF<<0<<" ";
}
/*----————————--处理完一行了----——---*/ 
}
OneHot<<endl;       //每一句新闻后都换行咯
TF<<endl;
TF_IDF<<endl;
}

//完成操作,关闭文件输出流 
OneHot.close();
TF.close();
TF_IDF.close();
SMATRIX1.close();
return 0;
}
0 0
原创粉丝点击