Search code examples
javamachine-learningweka

How do you copy a dataset's class values in weka?


I have two Instances datasets: data is the original and stumpyInsts is the one I am trying to copy the class values to. Here is my code:

FastVector attributes = new FastVector();
ArrayList<Instance> instances = new ArrayList<Instance>();
for(int i = 0; i <= 100; i++){
    Attribute newAttr = new Attribute("Stump" + i, i);
    attributes.addElement(newAttr);
}
//make new instances
Instances stumpyInsts = new Instances("Stumps", attributes, data.numInstances());

stumpyInsts.setClassIndex(stumpyInsts.numAttributes() - 1);
Enumeration instEnum = stumpyInsts.enumerateInstances();
Enumeration somethingElseLOL = data.enumerateInstances();
while (instEnum.hasMoreElements()) {
    Instance instance = (Instance) instEnum.nextElement();
    Instance other = (Instance) somethingElseLOL.nextElement();
    String s = other.stringValue(other.classIndex());
    instance.setValue(instance.classIndex(), s);
}

I keep getting this when I try to set the value:

`java.lang.IllegalArgumentException: Attribute neither nominal nor string!
at weka.core.Instance.setValue(Instance.java:687)`

Does anyone know why it happens? I also get the error if I try to setClassValue before adding the instance to the dataset, or if I make new strings with those values. To me it doesn't really make sense, since stringValue is clearly returning a string.


Solution

  • The error

    java.lang.IllegalArgumentException: Attribute neither nominal nor string!
      at weka.core.Instance.setValue(Instance.java:687)
    

    does not refer to stringValue, but to the class attribute of instance. When you do

    stumpyInsts.setClassIndex(stumpyInsts.numAttributes() - 1);
    

    you tell stumpyInsts what index its class is, but not that is should be a nominal or String attribute. According to this answer you would have to do something like

    FastVector classAttr = new FastVector();
    classAttr .addElement(new Attribute("class", (FastVector) null));
    

    to create a (class) attribute that has string or nominal values.