问题描述:
对实例集中的某个含有多个属性值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)两种情况,也只有这两个取值。