标称属性的概念分层

来源:互联网 发布:mac缺少图像源地址 编辑:程序博客网 时间:2024/06/02 19:44

tag:C++分离字符串;vector数组去重

问题的提出

数据挖掘>>数据预处理>>数据变换>>数据离散化>>标签属性的概念分层

  • 数据离散化:将连续属性的值域划分区间,便于数据挖掘,影响顶层决策
    以数值数据年龄为例,
    年龄是个连续属性,可以取0~100及以上的整数,单独研究特定年龄的样本数据并没有太大意义
    但年龄可以用区间标签(0~18,19~30,30~50,>50)或者概念标签(童年,青年,中年,老年)替换元素值,这样的研究成果才有指导价值
  • 标称属性的概念分层:便于将标称数据变换到多个粒度层
    以地址这个标称属性集为例,
    地址这个集合包含{区,市,省,国家}4个标称属性
    但没有相关数据语义的知识,未说明其偏序,如何找出任意的标称属性的分层序呢?这就是我今天要解决的问题.

解决办法

注意到一个启发规则:较高概念分层的属性,通常包含较少的不同值
以,国家这一属性包含的不同值的个数,
和省或者州包含的不同取值数比较,前者个数显然较少

问题抽象化

# #号开始的行是注释# 非注释行的第一行表示属性的名称,用空格或者tab隔开# 从第二行开始为数据#区   市   省   国家上城区 杭州市 浙江省 中国下城区 杭州市 浙江省 中国江干区 杭州市 浙江省 中国临安市 杭州市 浙江省 中国海曙区 宁波市 浙江省 中国江北区 宁波市 浙江省 中国江宁区 南京市 江苏省 中国秦淮区 南京市 江苏省 中国## 对本文件的处理后输出:# 概念分层从低到高应为:区 < 市 < 省 < 国家

编码思路

读取concept_input.txt中的内容
根据每个属性(字段)统计对应的不同值(种类)个数
从小到大排序
输出对应的属性字段到屏幕和concept_output.txt文件中

代码实现(C++)

#include<iostream>#include<fstream>#include<string>#include <vector>#include<algorithm>//分割字符串std::vector<std::string> split(std::string str,std::string pattern){    std::string::size_type pos;    std::vector<std::string> result;    str+=pattern;//扩展字符串以方便操作    for(int i=0; i<str.size(); i++)    {        pos=str.find(pattern,i);        if(pos<str.size())        {            std::string s=str.substr(i,pos-i);            result.push_back(s);            i=pos+pattern.size()-1;        }    }    return result;}//删除重复元素void elimDups(std::vector<std::string> &word){    // sort要包含头文件algorithm    std::sort(word.begin(),word.end());    //unique 重排输入范围,使得每个单词只出现一次    //返回排列的不重复区域后的一个位置的迭代器    std::vector<std::string>::iterator end_unique = std::unique(word.begin(),word.end());    //删除重复单词    word.erase(end_unique,word.end());}//定义一个类用来存储标字段及对应记录不同种类数目class Location{private:    std::string loc;    int num;public:    Location(std::string loc,int num){        this->loc = loc;        this->num = num;    }    Location(Location &l){loc=l.loc; num=l.num;}    int get_num(){return num;}    std::string get_loc(){return loc;}};int main(){    std::string s;    bool flag = true;    std::ifstream fin;    std::ofstream fout;    //field字段数组,对应 区,市,省,国家等    //tuple元组    //l1-4 四个字段分别对应的记录数    std::vector<std::string> field,tuple,l1,l2,l3,l4,l[4];    fin.open("concept_input.txt");    fout.open("concept_output.txt");    //==读入数据    while(!fin.eof())    {        std::getline(fin,s);         if(s[0]=='#'||s[0]==NULL)            continue;        else{            if(flag){// 分割第一行                field=split(s," ");                     flag = false;            }            else{   //将之后的每行的元素添加到content中                tuple=split(s," ");                l[0].push_back(tuple[0]);                l[1].push_back(tuple[1]);                l[2].push_back(tuple[2]);                l[3].push_back(tuple[3]);                       }        }       }    //==消除重复 之后l1的大小即为其元素个数    elimDups(l1);    elimDups(l2);    elimDups(l3);    elimDups(l4);    //将字段field与其对应的值一一对应起来    Location A[5]={Location(field[0],l[0].size()),//哨兵        Location(field[0],l[0].size()),        Location(field[1],l[1].size()),        Location(field[2],l[2].size()),        Location(field[3],l[3].size())};    //直接插入排序    int i,j;    for(i=2; i<=4; i++){        A[0] = A[i];        for(j = i -1; A[0].get_num()<A[j].get_num(); --j )            A[j+1] = A[j];        A[j+1] = A[0];          }    //输出    std::cout<<"自动产生这些属性的概念分层从低到高为:"<<std::endl;    for(i=1; i<=4; ++i)    {        std::cout<<A[i].get_loc()<<" < ";        //输出到文件        fout<<A[i].get_loc()<<" < ";    }    fin.close();    fout.close();    std::cout<<std::endl;    system("pause");    return 0;}

补充

太久没用C++了,想用标准C实现,但代码写的有点蠢,
一些C++的标准容器的用法还不太熟悉,(尤其是关联容器map,set等)
导致前半部分和后半部分的代码风格截然不同.

最重要的这种启发式的规则并非万无一失

0 0
原创粉丝点击