将多个属性值的属性中的某些属性值整合成一个属性值

来源:互联网 发布:电子宠物机多少钱知乎 编辑:程序博客网 时间:2024/06/16 21:05

问题描述:
对实例集中的某个含有多个属性值value的属性attribute,有时候需要将其中的多个属性值整合成一个属性值。转换后的实例集中,每个实例对应属性attribute的属性值也要对应着修改后的属性值。
例如,(1)数据集weather的属性outlook有三个属性值(sunny,overcast,rainy),如何将(sunny,overcast)两个属性值整合成一个属性值;(2)数据集vehicle的类属性有四个属性值(opel,saab,bus,van),如何将第2至第4个属性值整合成一个属性值。这类问题将在下面的过程中解决。

问题解决:
1. 对非类属性
对非类属性的处理比较简单,可以在weka中直接用过滤器来处理,这里以第一个例子进行步骤说明。
1) 首先,用weka的Explorer打开weather.arff文件,可以看到属性outlook的信息如下:
这里写图片描述
2) 其次,在Filter部分选择choose,按照如下顺序选择过滤器:filters->unsupervised->attribute->MergeTwoValue
这里写图片描述
3) 接着,设置参数如下:
这里写图片描述
其中第一个参数attributeIndex是要处理的属性outlook的下标(为1,左上角处可以看到),第二个firstValueIndex第三个参数secondValueIndex分别表示要整合成起来的两个属性值下标,这里是指sunny和overcast的下标(分别为1和2,从右上角处可以看到)。点击OK。
4) 点击Apply按钮即可看到属性值整合后的效果如图:
这里写图片描述
这样就把属性outlook的两个属性值sunny和overcast整合成一个属性值sunny_overcast了。将其保存为新的arff文件,再用ArffViwer打开该新的arff文件,即可看到每个实例的outlook属性也相应的改变了:
这里写图片描述
注意:由于过滤器MergeTwoValue是将两个属性值整合成一个属性值,所以要将多个属性值整合成一个属性值,就多次处理即可。

2. 对类属性
之所以要单独讨论类属性的属性值整合处理,是因为过滤器MergeTwoValue在对类属性进行处理时会有如下错误提示,即无法处理类属性:
这里写图片描述
所以这里需要编写源代码自己对类属性进行处理。下面以第二个例子进行解释说明,部分代码参考weka.filters.unsupervised.attribute.MergeTwoValues.java代码。
注意,代码中将属性值opel设置成0,将(saab,bus,van)三个属性值整合成一个并设置为1.
输入:读取vehicle.arff文件得到的实例集instances,
输出:类属性值整合后的实例集newInstances。
代码:

//对每个实例的类属性值进行修改,for (int i = 0; i < instances.numInstances(); i++)        {       weka.core.Instance instance = instances.instance(i);       if (instance.classValue() == 0.0)//属性值是opel的实例,将其类属性值都设置为0            instance.setClassValue(Integer.toString(0));        if (instance.classValue() != 0.0)//属性值是(saab,bus,van)的实例,将其类属性值都设置为1            instance.setClassValue(Integer.toString(1));  }//创建新的属性向量newAttributes    FastVector newAttributes = new FastVector(instances.numAttributes());     for (int i = 0; i < instances.numAttributes(); i++)        {            if (i != instances.classIndex()) //添加非处理的属性到newAttributes中                newAttributes.addElement(instances.attribute(i).copy());        }    Attribute attribute = instances.classAttribute();    FastVector newValues = new FastVector(attribute.numValues() - 2);//整合后的属性的属性值向量,括号内的参数是整合后的属性的属性值个数    newValues.addElement(attribute.value(0)); //设置第一个属性值    newValues.addElement(attribute.value(1)); //设置第二个属性值    Attribute newAttribute = new Attribute(attribute.name(), newValues); //整合后的属性    newAttribute.setWeight(attribute.weight());    newAttributes.addElement(newAttribute);//将整合后的属性加入属性向量中//创建新的实例集newInstances    Instances newInstances = new Instances(instances.relationName(), newAttributes, instances.numInstances());    for (int i = 0; i < instances.numInstances(); i++) //将instances中的实例逐个加入到实例集newInstances中        {            weka.core.Instance instance = instances.instance(i);            newInstances.add(instance);        }    newInstances.setClassIndex(instances.classIndex());    weka.filters.Filter filter= new Filter()     {    };    filter.setInputFormat(newInstances);

将newInstances保存为新的arff文件,打开该新的arff文件即可看到vehicle的类属性只有0(对应opel)和1(对应saab,bus,van)两种情况,也只有这两个取值。
这里写图片描述