我需要迭代地使用SparseInstance对象扩展一个Weka ARFF文件。每次添加一个新的SparseInstance时,头部可能会改变,因为新的实例可能会添加额外的属性。我以为mergeInstances方法可以解决我的问题,但它并不能。它要求两个数据集没有共享的属性。
如果这还不够清楚,请看以下示例:
Dataset1a b c1 2 34 5 6Dataset2c d7 8合并结果:a b c d1 2 3 ?4 5 6 ?? ? 7 8
目前我能想到的唯一解决方案是手动解析arff文件,并使用字符串处理进行合并。有人知道更好的解决方案吗?
回答:
好的。我自己找到了解决方案。解决方案的核心部分是Instances#insertAttributeAt
方法,如果第二个参数是model.numAttributes()
,它会将新属性插入到最后。这里是针对数值属性的示例代码。也很容易适应其他类型的属性:
Map<String,String> currentInstanceFeatures = currentInstance.getFeatures(); Instances model = null; try { if (targetFile.exists()) { FileReader in = new FileReader(targetFile); try { BufferedReader reader = new BufferedReader(in); ArffReader arff = new ArffReader(reader); model = arff.getData(); } finally { IOUtils.closeQuietly(in); } } else { FastVector schema = new FastVector(); model = new Instances("model", schema, 1); } Instance newInstance = new SparseInstance(0); newInstance.setDataset(model); for(Map.Entry<String,String> feature:currentInstanceFeatures.entrySet()) { Attribute attribute = model.attribute(feature.getKey()); if (attribute == null) { attribute = new Attribute(feature.getKey()); model.insertAttributeAt(attribute, model.numAttributes()); attribute = model.attribute(feature.getKey()); } newInstance.setValue(attribute, feature.getValue()); } model.add(newInstance); model.compactify(); ArffSaver saver = new ArffSaver(); saver.setInstances(model); saver.setFile(targetFile); LOGGER.debug("Saving dataset to: " + targetFile.getAbsoluteFile()); saver.writeBatch(); } catch (IOException e) { throw new IllegalArgumentException(e); }