/*********************************************************************** This file is part of KEEL-software, the Data Mining tool for regression, classification, clustering, pattern mining and so on. Copyright (C) 2004-2010 F. Herrera (herrera@decsai.ugr.es) L. S�nchez (luciano@uniovi.es) J. Alcal�-Fdez (jalcala@decsai.ugr.es) S. Garc�a (sglopez@ujaen.es) A. Fern�ndez (alberto.fernandez@ujaen.es) J. Luengo (julianlm@decsai.ugr.es) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ **********************************************************************/ /* * UciToKeel.java */ package keel.Algorithms.Preprocess.Converter; import keel.Dataset.*; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.FileReader; import java.util.*; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.Ostermiller.util.CSVParser; /** * <p> * <b> UciToKeel </b> * </p> * * Clase extendida de la clase Importer. Esta clase permite convertir * un fichero de datos con formato Uci (con formato C4.5) a formato de * datos Keel. El fichero Uci está compuesto de dos ficheros, un * fichero de nombres con extensión ".names" que contiene la * definición de los atributos y un fichero de datos con extensión * ".data" que almacena los datos con formato csv. * * @author Teresa Prieto López (UCO) * @version 1.0 */ public class UciToKeel extends Importer { // Etiqueta para el valor IGNORE del fichero de nombres. int IGNORE = -2; /* * Constructor de la Clase UciToKeel. Inicializa los valores * de las variables miembro separator (separador de los datos del fichero de datos ".data" ) * con el valor del parámetro separatorUser. * * @param separatorUser. Variable de tipo String con el separador de los * datos para el fichero de datos ".data". * */ public UciToKeel(String separatorUser) { separator = separatorUser; } /* * Método utilizado para convertir los datos de los ficheros * de entrada con formato UCI (fichero de datos con la variable * pathnameInputData y fichero de nombres con la variable pathnameInputNames) * a formato keel en el fichero indicado por la ruta pathnameOutput * * @param pathnameInputNames Variable String que almacena * la ruta del fichero de nombres (".names"). * @param pathnameInputData Variable String que almacena * la ruta del fichero de datos (".data"). * @param pathnameOutput ruta para el fichero de datos Keel. * * @throws Exception */ public void Start(String pathnameInputNames, String pathnameInputData, String pathnameOutput) throws Exception { Pattern p; Matcher m; File f; BufferedReader reader; BufferedWriter auxFile; String element = new String(); String filenameNames = "tempOf"; String filenameData = "tempOf"; String line = new String(); String nameAttribute = new String(); String lineReduced = new String(); int i = 0; int j = 0; int type = -1; int actualValueInt; double actualValue; double min; double max; // Limpio los caracteres no válidos del ficheros de nombres File fileInputNames = new File(pathnameInputNames); filenameNames = filenameNames.concat(fileInputNames.getName()); reader = new BufferedReader(new FileReader(pathnameInputNames)); auxFile = new BufferedWriter(new FileWriter(filenameNames)); while ((line = reader.readLine()) != null) { if (!line.equals("") && !line.startsWith("|")) { //Quitamos los comentarios if (line.contains("|")) { line = line.substring(0, line.indexOf('|')); //Quitamos los espacios al principio de la línea } p = Pattern.compile("^\\s+"); m = p.matcher(line); line = m.replaceAll(""); //Quitamos los espacios al final de la línea p = Pattern.compile("\\s+$"); m = p.matcher(line); line = m.replaceAll(""); // Quitamos el punto al final de la línea p = Pattern.compile("[.]$"); m = p.matcher(line); line = m.replaceAll(""); //Elimino cualquier valor escapado p = Pattern.compile("\\\\."); m = p.matcher(line); line = m.replaceAll(""); //Quitamos los espacios delante y detrás de las comas p = Pattern.compile("\\s*,\\s*"); m = p.matcher(line); line = m.replaceAll(","); //Quitamos los espacios delante y detrás de los dos puntos p = Pattern.compile("\\s*:\\s*"); m = p.matcher(line); line = m.replaceAll(":"); p = Pattern.compile("\\s+"); m = p.matcher(line); line = m.replaceAll(" "); auxFile.write(line + "\n"); } } auxFile.close(); reader.close(); // Limpio los caracteres no válidos del ficheros de datos File fileInputData = new File(pathnameInputData); filenameData = filenameData.concat(fileInputData.getName()); reader = new BufferedReader(new FileReader(pathnameInputData)); auxFile = new BufferedWriter(new FileWriter(filenameData)); while ((line = reader.readLine()) != null) { if (!line.equals("") && !line.startsWith("|")) { //Quitamos los comentarios if (line.contains("|")) { line = line.substring(0, line.indexOf('|')); //Quitamos los espacios al principio de la línea } p = Pattern.compile("^\\s+"); m = p.matcher(line); line = m.replaceAll(""); //Quitamos los espacios al final de la línea p = Pattern.compile("\\s+$"); m = p.matcher(line); line = m.replaceAll(""); // Quitamos el punto al final de la línea p = Pattern.compile("[.]$"); m = p.matcher(line); line = m.replaceAll(""); //Elimino cualquier valor escapado p = Pattern.compile("\\\\."); m = p.matcher(line); line = m.replaceAll(""); //Quitamos los espacios delante y detrás de las comas p = Pattern.compile("\\s*,\\s*"); m = p.matcher(line); line = m.replaceAll(","); p = Pattern.compile("\\s+"); m = p.matcher(line); line = m.replaceAll(" "); auxFile.write(line + "\n"); } } auxFile.close(); reader.close(); // Leo el fichero para ver cuantos atributos existen reader = new BufferedReader(new FileReader(filenameNames)); //Contamos el numero de atributos i = 0; while ((line = reader.readLine()) != null) { if (line.contains(":")) { i++; } } reader.close(); numAttributes = i; //Reservamos memoria para almacenar la definición de los atributos y de los datos attribute = new Attribute[numAttributes]; data = new Vector[numAttributes]; types = new Vector[numAttributes]; for (i = 0; i < numAttributes; i++) { attribute[i] = new Attribute(); data[i] = new Vector(); types[i] = new Vector(); } // Leo del fichero generado con valores válidos reader = new BufferedReader(new FileReader(filenameNames)); //Saltamos la primera línea que corresponde al nombre de las clases. line = reader.readLine(); i = 0; while ((line = reader.readLine()) != null) { if (line.contains(":")) { nameAttribute = line.substring(0, line.indexOf(":")); nameAttribute = nameAttribute.replace("'", ""); p = Pattern.compile("\\s+"); m = p.matcher(nameAttribute); nameAttribute = m.replaceAll(" "); if (nameAttribute.contains(" ")) { StringTokenizer token = new StringTokenizer(nameAttribute, " "); String lineAux = ""; if (token.hasMoreTokens()) { lineAux = token.nextToken(); } while (token.hasMoreTokens()) { lineAux = lineAux.concat(UcFirst(token.nextToken())); } nameAttribute = lineAux; } if (nameAttribute.equals("") || nameAttribute.equals("?") || nameAttribute.equals("<null>")) { nameAttribute = "ATTRIBUTE_" + (i + 1) + ""; } attribute[i].setName(nameAttribute); lineReduced = line.substring(line.indexOf(":") + 1, line.length()).toLowerCase(); if (lineReduced.startsWith("ignore")) { attribute[i].setType(IGNORE); } else { if (!lineReduced.startsWith("discrete") && !lineReduced.startsWith("continuous")) { lineReduced = line.substring(line.indexOf(":") + 1, line.length()); if (lineReduced != "") { StringTokenizer listValues = new StringTokenizer(lineReduced, ","); attribute[i].setType(NOMINAL); while (listValues.hasMoreTokens()) { element = (String) listValues.nextToken(); p = Pattern.compile("[^A-ZÑa-zñ0-9_-]+"); m = p.matcher(element); /** * Cambio hecho para que los nominales con espacios en blanco se dejen * con subrayado bajo "_" y sin comillas simples. Se añade la siguiente linea */ element = element.replace(" ", "_"); if (m.find() && !element.startsWith("'") && !element.endsWith("'") && !element.equals("?")) /** * Cambio hecho para que los nominales con espacios en blanco se dejen * con subrayado bajo "_" y sin comillas simples. Se comenta la siguiente linea */ /* //element="'"+element+"'"; */ { attribute[i].addNominalValue(element); } } } }//end if }//end else i++; } } reader.close(); numAttributes = i; FileReader filereader = new FileReader(filenameData); String[][] values = CSVParser.parse(filereader, separator.charAt(0)); filereader.close(); for (i = 0; i < values.length; i++) { for (j = 0; j < numAttributes; j++) { element = values[i][j]; p = Pattern.compile("^\\s+"); m = p.matcher(element); element = m.replaceAll(""); p = Pattern.compile("\\s+$"); m = p.matcher(element); element = m.replaceAll(""); element = element.replace("\r", " "); element = element.replace("\n", " "); if (element.equals("") || element.equals(nullValue) || element.equals("<null>")) { element = "?"; } data[j].addElement(element); } } // Asignamos el tipo de los atributos for (i = 0; i < data[0].size(); i++) { for (j = 0; j < numAttributes; j++) { element = (String) data[j].elementAt(i); if (attribute[j].getType() == -1) { types[j].addElement(DataType(element)); } } } for (i = 0; i < numAttributes; i++) { if (attribute[i].getType() != IGNORE && attribute[i].getType() == -1) { if (types[i].contains(NOMINAL)) { attribute[i].setType(NOMINAL); } else { if (types[i].contains(REAL)) { attribute[i].setType(REAL); } else { if (types[i].contains(INTEGER)) { attribute[i].setType(INTEGER); } else { attribute[i].setType(-1); } } } } } for (i = 0; i < data[0].size(); i++) { for (j = 0; j < numAttributes; j++) { element = (String) data[j].elementAt(i); type = attribute[j].getType(); if (type == NOMINAL) { p = Pattern.compile("[^A-ZÑa-zñ0-9_-]+"); m = p.matcher(element); /** * Cambio hecho para que los nominales con espacios en blanco se dejen * con subrayado bajo "_" y sin comillas simples. Se añade la siguiente linea */ element = element.replace(" ", "_"); if (m.find() && !element.startsWith("'") && !element.endsWith("'") && !element.equals("?")) { /** * Cambio hecho para que los nominales con espacios en blanco se dejen * con subrayado bajo "_" y sin comillas simples. Se comenta la siguiente linea */ /* //element="'"+element+"'"; */ data[j].set(i, element); } if (!(attribute[j].isNominalValue(element)) && !element.equals("?")) { attribute[j].addNominalValue(element); } } if (type == INTEGER) { if (!element.equals("?")) { actualValueInt = Integer.valueOf(element); data[j].set(i, actualValueInt); if ((attribute[j].getFixedBounds()) == false) { attribute[j].setBounds(actualValueInt, actualValueInt); } else { min = attribute[j].getMinAttribute(); max = attribute[j].getMaxAttribute(); if (actualValueInt < min) { attribute[j].setBounds(actualValueInt, max); } if (actualValueInt > max) { attribute[j].setBounds(min, actualValueInt); } } } } if (type == REAL) { if (!element.equals("?")) { actualValue = Double.valueOf(element); data[j].set(i, actualValue); if ((attribute[j].getFixedBounds()) == false) { attribute[j].setBounds(actualValue, actualValue); } else { min = attribute[j].getMinAttribute(); max = attribute[j].getMaxAttribute(); if (actualValue < min) { attribute[j].setBounds(actualValue, max); } if (actualValue > max) { attribute[j].setBounds(min, actualValue); } } } } }//end while }//end while /* Insertamos el nombre de la relación que será el mismo que el del * fichero pasado, pero sin extensión*/ nameRelation = fileInputNames.getName(); p = Pattern.compile("\\.[A-Za-z]+"); m = p.matcher(nameRelation); nameRelation = m.replaceAll(""); p = Pattern.compile("\\s+"); m = p.matcher(nameRelation); nameRelation = m.replaceAll(""); //Borramos los ficheros temporales f = new File(filenameNames); f.delete(); f = new File(filenameData); f.delete(); // Llamamos a save para que me transforme los datos almacenamos a formato keel Save(pathnameOutput); } /* * Este método crea el fichero de salida con formato keel en la ruta pasada, * a partir de la información almacenada en las variables miembro * attribute[], data[], nameRelation y numAttributes. * Aquellos atributos con etiqueta IGNORE en el fichero de nombres, * no son almacenados en el fichero de salida. * * @param String pathnameOutput Indica la ruta del fichero de salida con formato Keel. * * @throws Exception */ @Override public void Save(String pathnameOutput) throws Exception { Vector dataAux[]; Attribute attributeCurrent = new Attribute(); String filename = pathnameOutput; String line = new String(); int i; int j; int k; int cont = 0; /* Comprobamos si el nombre del fichero tiene la extensión .dat, si no la tiene * se la ponemos */ if (pathnameOutput.endsWith(".dat")) { filename = pathnameOutput; } else { filename = pathnameOutput.concat(".dat"); } FileWriter fileWriter = new FileWriter(filename); fileWriter.write("@relation " + nameRelation + "\n"); for (i = 0; i < numAttributes; i++) { attributeCurrent = attribute[i]; if (attributeCurrent.getType() != IGNORE) { if (attributeCurrent.getType() != -1) { line = attributeCurrent.toString(); fileWriter.write(line + "\n"); } else { fileWriter.write("@attribute " + attributeCurrent.getName() + " REAL\n"); } } } cont = 0; for (i = 0; i < numAttributes; i++) { attributeCurrent = attribute[i]; if (attributeCurrent.getType() != IGNORE) { cont++; } } dataAux = new Vector[cont]; for (i = 0; i < cont; i++) { dataAux[i] = new Vector(); } k = 0; for (i = 0; i < numAttributes; i++) { attributeCurrent = attribute[i]; if (attributeCurrent.getType() != IGNORE) { for (j = 0; j < data[0].size(); j++) { dataAux[k].addElement(data[i].elementAt(j)); } k++; } } fileWriter.write("@inputs "); for (i = 0; i < numAttributes-1; i++) { fileWriter.write(attribute[i].getName() ); if(i!=numAttributes-2) fileWriter.write(", "); else fileWriter.write("\n"); } fileWriter.write("@outputs " ); fileWriter.write(attribute[numAttributes-1].getName() + "\n"); fileWriter.write("@data" + "\n"); for (i = 0; i < dataAux[0].size(); i++) { for (j = 0; j < dataAux.length; j++) { if (j == (numAttributes - 1)) { fileWriter.write(dataAux[j].elementAt(i) + ""); } else { fileWriter.write(dataAux[j].elementAt(i) + ","); } } fileWriter.write("\n"); } fileWriter.close(); File f = new File(filename); System.out.println("Fichero " + f.getName() + " convertido correctamente"); }//end save() }//end UciToKeel()