ArffDatasetAdapter implements IDatasetDeserializer<ILabeledDataset<ILabeledInstance>> { protected static Object parseInstance(final boolean sparseData, final List<IAttribute> attributes, final int targetIndex, final String line) { if (line.trim().startsWith("%")) { throw new IllegalArgumentException("Cannot create object for commented line!"); } boolean sparseMode = sparseData; String curLine = line; if (curLine.trim().startsWith("{") && curLine.trim().endsWith("}")) { curLine = curLine.substring(1, curLine.length() - 1); if (curLine.trim().isEmpty()) { return new HashMap<>(); } } String[] lineSplit = curLine.split(","); if (!(lineSplit[0].startsWith("'") && lineSplit[0].endsWith("'") || lineSplit[0].startsWith("\"") && lineSplit[0].endsWith("\"")) && lineSplit[0].contains(" ") && tryParseInt(lineSplit[0].split(" ")[0])) { sparseMode = true; } if (!sparseMode) { if (lineSplit.length != attributes.size()) { throw new IllegalArgumentException("Cannot parse instance as this is not a sparse instance but has less columns than there are attributes defined. Expected values: " + attributes.size() + ". Actual number of values: " + lineSplit.length + ". Values: " + Arrays.toString(lineSplit)); } Object[] parsedDenseInstance = new Object[lineSplit.length - 1]; Object target = null; int cI = 0; for (int i = 0; i < lineSplit.length; i++) { final Object value; if (lineSplit[i].trim().equals(V_MISSING_VALUE)) { value = null; } else { value = attributes.get(i).deserializeAttributeValue(lineSplit[i]); } if (i == targetIndex) { target = value; } else { parsedDenseInstance[cI++] = value; } } return Arrays.asList(parsedDenseInstance, target); } else { Map<Integer, Object> parsedSparseInstance = new HashMap<>(); for (String sparseValue : lineSplit) { sparseValue = sparseValue.trim(); int indexOfFirstSpace = sparseValue.indexOf(' '); int indexOfAttribute = Integer.parseInt(sparseValue.substring(0, indexOfFirstSpace)); if (indexOfAttribute > targetIndex) { indexOfAttribute--; } String attributeValue = sparseValue.substring(indexOfFirstSpace + 1); parsedSparseInstance.put(indexOfAttribute, attributes.get(indexOfAttribute).deserializeAttributeValue(attributeValue)); } return parsedSparseInstance; } } ArffDatasetAdapter(final boolean sparseMode, final IDatasetDescriptor datasetDescriptor);  ArffDatasetAdapter(final boolean sparseMode);  ArffDatasetAdapter(); IAttribute getAttributeWithName(final IFileDatasetDescriptor datasetFile, final String nameOfAttribute); ILabeledDataset<ILabeledInstance> deserializeDataset(final IFileDatasetDescriptor datasetFile, final String nameOfClassAttribute); ILabeledDataset<ILabeledInstance> deserializeDataset(final IFileDatasetDescriptor datasetDescriptor, final int columnWithClassIndex); @Override ILabeledDataset<ILabeledInstance> deserializeDataset(final IDatasetDescriptor datasetDescriptor); ILabeledDataset<ILabeledInstance> deserializeDataset(); static ILabeledDataset<ILabeledInstance> readDataset(final File datasetFile); static ILabeledDataset<ILabeledInstance> readDataset(final boolean sparseMode, final File datasetFile); static ILabeledDataset<ILabeledInstance> readDataset(final boolean sparseMode, final File datasetFile, final int columnWithClassIndex); static void serializeDataset(final File arffOutputFile, final ILabeledDataset<? extends ILabeledInstance> data); static final String V_MISSING_VALUE; static final String K_RELATION_NAME; static final String K_CLASS_INDEX; }
@Test public void testParseSparseInstance() { String testInstanceLine = generateSparseInstanceString(TEST_ATTRIBUTES, TEST_INSTANCE); Object parsedInstance = ArffDatasetAdapter.parseInstance(true, TEST_ATTRIBUTES, CLASS_INDEX, testInstanceLine); assertTrue("The returned instance is not in the expected sparse instance format", parsedInstance instanceof Map); @SuppressWarnings("unchecked") Map<Integer, Object> parsedSparseInstance = (Map<Integer, Object>) parsedInstance; for (int i = 0; i < TEST_INSTANCE.length; i++) { assertEquals("Attribute value at position " + i + " " + parsedSparseInstance.get(i) + " is not equal to the expected value " + TEST_INSTANCE[i], TEST_INSTANCE[i], parsedSparseInstance.get(i)); } assertTrue("Numeric attribute is not a Number object but of type " + parsedSparseInstance.get(0).getClass().getName(), parsedSparseInstance.get(0) instanceof Number); assertNotNull("No instance label for sparse instance " + parsedSparseInstance, parsedSparseInstance.get(CLASS_INDEX)); }
@Test public void testThatMissingNumericValuesAreNullInDenseInstances() { String testInstanceLine = generateDenseInstanceString(TEST_ATTRIBUTES, TEST_INSTANCE_WITH_MISSING_NUMERIC_VAL); Object parsedInstance = ArffDatasetAdapter.parseInstance(false, TEST_ATTRIBUTES, CLASS_INDEX, testInstanceLine); assertTrue("The returned instance is not in the expected dense instance format", parsedInstance instanceof List<?>); Object[] parsedDenseInstance = (Object[]) ((List<?>) parsedInstance).get(0); Object label = ((List<?>) parsedInstance).get(1); assertNull(parsedDenseInstance[0]); assertNotNull(label); }
@Test public void testThatMissingCategoricalValuesAreNullInDenseInstances() { String testInstanceLine = generateDenseInstanceString(TEST_ATTRIBUTES, TEST_INSTANCE_WITH_MISSING_CATEGORICAL_VAL); Object parsedInstance = ArffDatasetAdapter.parseInstance(false, TEST_ATTRIBUTES, CLASS_INDEX, testInstanceLine); assertTrue("The returned instance is not in the expected dense instance format", parsedInstance instanceof List<?>); Object[] parsedDenseInstance = (Object[]) ((List<?>) parsedInstance).get(0); Object label = ((List<?>) parsedInstance).get(1); assertNull(label); assertNotNull(parsedDenseInstance[0]); }
@Test public void testThatMissingNumericValuesAreNullInSparseInstances() { String testInstanceLine = generateSparseInstanceString(TEST_ATTRIBUTES, TEST_INSTANCE_WITH_MISSING_NUMERIC_VAL); Object parsedInstance = ArffDatasetAdapter.parseInstance(true, TEST_ATTRIBUTES, CLASS_INDEX, testInstanceLine); @SuppressWarnings("unchecked") Map<Integer, Object> parsedSparseInstance = (Map<Integer, Object>) parsedInstance; assertNull(parsedSparseInstance.get(0)); assertNotNull(parsedSparseInstance.get(1)); assertNotNull(parsedSparseInstance.get(2)); }
@Test public void testThatMissingCategoricalValuesAreNullInSparseInstances() { String testInstanceLine = generateSparseInstanceString(TEST_ATTRIBUTES, TEST_INSTANCE_WITH_MISSING_CATEGORICAL_VAL); Object parsedInstance = ArffDatasetAdapter.parseInstance(true, TEST_ATTRIBUTES, CLASS_INDEX, testInstanceLine); @SuppressWarnings("unchecked") Map<Integer, Object> parsedSparseInstance = (Map<Integer, Object>) parsedInstance; assertNotNull(parsedSparseInstance.get(0)); assertNotNull(parsedSparseInstance.get(1)); assertNull(parsedSparseInstance.get(2)); }
@Test public void testParseDenseInstance() { String testInstanceLine = generateDenseInstanceString(TEST_ATTRIBUTES, TEST_INSTANCE); Object parsedInstance = ArffDatasetAdapter.parseInstance(false, TEST_ATTRIBUTES, CLASS_INDEX, testInstanceLine); assertTrue("The returned instance is not in the expected dense instance format", parsedInstance instanceof List<?>); Object[] parsedDenseInstance = (Object[]) ((List<?>) parsedInstance).get(0); Object label = ((List<?>) parsedInstance).get(1); assertEquals("The size of the array is varying.", TEST_INSTANCE.length, parsedDenseInstance.length + 1); for (int i = 0; i < TEST_INSTANCE.length; i++) { if (i == CLASS_INDEX) { assertEquals("Attribute value at position " + i + " " + label + " is not equal to the expected value " + TEST_INSTANCE[i], TEST_INSTANCE[i], label); } else { assertEquals("Attribute value at position " + i + " " + parsedDenseInstance[i] + " is not equal to the expected value " + TEST_INSTANCE[i], TEST_INSTANCE[i], parsedDenseInstance[i]); } } assertTrue("Numeric attribute is not a Number object but of type " + parsedDenseInstance[0].getClass().getName(), parsedDenseInstance[0] instanceof Number); assertNotNull("No instance label for dense instance " + parsedInstance, ((List<?>) parsedInstance).get(1)); }