Práctica Final
INTELIGENCIA EN
REDES DE
COMUNICACIONES
Minería de Datos:
Predicción de las
condiciones meteorológicas
Carlos Blanco González
Fernando García Diez
Grupo 91 – 5º curso Ing. telecomunicación
1. Introducción
El objetivo de esta práctica es obtener un sistema de predicción meteorológica para la ciudad de Madrid, para lo cual se van a usar técnicas de minería de datos sobre un conjunto extenso de datos extraídos durante aproximadamente 8 años en el
aeropuerto de Barajas.
La minería de datos nos proporciona toda una serie de técnicas para la selección, procesado, clasificación, evaluación e interpretación de la información, para poder conseguir que, dado un gran volumen de datos se consiga extraer un conocimiento y así poder predecir futuros comportamientos o acciones.
Mediante las diferentes etapas en que podríamos dividir el proceso de minería de datos (preprocesado, selección de características, extracción de conocimiento, interpretación y evaluación) conseguimos pasar de una secuencia de datos a un modelo de conocimiento.
Para alcanzar este modelo de conocimiento vamos a usar la herramienta WEKA, en la que podemos realizar las diferentes etapas anteriormente citadas. En WEKA podemos distinguir entre técnicas descriptivas y predictivas. Con las técnicas
descriptivas tenemos la capacidad de saber que variables de los datos son más valiosas y así poder seleccionarlas para que a la hora de aplicar las técnicas predictivas obtener
resultados mejores. Además tenemos herramientas para filtrar la información según nosotros queramos, al igual que técnicas de visualización de los datos y de las relaciones que existen entre ellos.
Las técnicas predictivas consisten en una serie de algoritmos que buscan
relaciones entre los datos para estimar una determinada variable, y se evalúan con unos determinados datos que se le pasan como test. Los algoritmos que nosotros vamos a usar son:
Decisión Table: Una tabla de decisión es una manera conveniente de organizar información de una manera sistemática. Están orientadas a la resolución de una sola meta. Las alternativas son listadas con su suposición de contribución en manera de tabla y según esto se decide.
REPTree: Funcionamiento en dos fases (datos de aprendizaje y datos de poda). Primero se crea un conjunto de reglas que se sobreajusta a los datos usados para el aprendizaje, después se poda el conjunto de reglas usando ejemplares que no participaron en el aprendizaje.
SMOreg: Implementa el algoritmo de optimización de secuencia mínima desarrollado por John C. Esta implementación sustituye todos los valores que faltan y transforma atributos nominales en otros binarios. También normaliza todos los atributos por defecto (los coeficientes a la salida están basados en los datos normalizados, no en los originales).
Kstar: Es un clasificador basado en las variables, lo que quiere decir que la clasificación de una variable está basada en variables de entrenamiento similares, determinadas por alguna función de similitud. Se diferencia de otros aprendizajes basados en lo mismo en que usa una función de distancia basada en entropía.
Linear Regression: Implementa una regresión lineal a partir de un muestreo de datos aleatorio. La regresión ajustada con el error cuadrático medio más bajo se elige como el modelo final.
2. Preprocesado
La parte más importante de esta práctica consiste en el preprocesado de los datos. Disponemos de un conjunto de datos muy grande entre los cuales hay incluidos valores atípicos que deben ser eliminados y otros valores que no nos interesan o que el programa Weka no es capaz de entender.
Los archivos de partida se encuentran en formato METAR. Existe un archivo para cada uno de los días, que contiene una línea de texto para cada medición
meteorológica. Estas líneas tienen la siguiente forma:
5:00 AM,32.0,30.2,93,30.30,7.0,Calm,Calm,-,N/A,,Parcialmente Nublado Donde se indican separados por comas los siguientes atributos en este orden: Hora, Temperatura (ºF), Nivel de Rocío (ºF), Humedad, Presión, Visibilidad (mph), dirección del viento, Velocidad del viento (mph), velocidad de ráfaga (mph), Precipitación, Hechos y Condiciones.
Sin embargo, los archivos que entiende Weka deben estar en formato arff (Attribute-Relation File Format), el fichero tendrá una cabecera donde se indica qué atributos lleva cada línea y de que tipo son (numérico o de clases fundamentalmente, en cuyo caso se indican los posibles valores que puede tomar el atributo), y a continuación aparecerán los datos en sí, con una línea para cada medida con los atributos separados por comas y signos de interrogación “?” para los datos que no se conozcan.
Para pasar de un formato de fichero a otro se han implementado varios programas java que, para empezar, juntan todos los archivos de las distintas fechas en uno sólo, añadiendo al principio de cada línea tres nuevos atributos que son la fecha, mes y año, que originalmente aparecían en el nombre del fichero, y cambiando el formato de los saltos de línea. A continuación se sustituyen por signos de interrogación muchos datos inválidos o no existentes, como “N/A”, “-“, “-9999.0” o simplemente un atributo vacío.
También hacía falta redondear las horas para que las medidas estuvieran separadas cada media hora, pasando la medida de, por ejemplo las 12:02 a las 12:00 para que no se tome como un número distinto.
Sin embargo, llegados a este punto comenzamos a usar un fichero
proporcionado por el profesor en el que ya se habían modificado las horas para que fueran un número de 0 a 48 y se habían añadido muestras con todos los datos “?” para las horas que no tenían medidas. Comenzamos pues a modificar este fichero,
reemplazando todos los “N/A”, “-“, “-9999.0” y atributos vacíos por interrogaciones. Al intentar definir en el fichero arff los distintos valores que podían tomar las variables no numéricas encontramos valores aislados tanto en el campo de hechos como en el de condiciones, valores que se daban muy pocas veces y que por tanto no eran representativos, como “nubes de polvo” o “granizo”, que se dan una o dos veces en todo el fichero. En este caso hemos optado por eliminar ese valor sustituyéndolo por una interrogación, ya que no tenía sentido cargar computacionalmente al algoritmo por un hecho tan aislado.
También se ha dado el caso de valores que eran muy similares a otros ya definidos (“Abundantes Lluvias” y “Lluvias”), y lo que se ha hecho en este caso con ellos es agruparlos con otro tipo de condiciones similares (convertir “altamente nublado” a “nublado”, por ejemplo) mediante una sustitución simple en un programa java.
Además de los datos que aparecen inicialmente, seguimos modificando el fichero y añadimos al final de cada línea más atributos tomados de líneas posteriores o anteriores: temperatura dentro de 1h y 24h, condiciones meteorológicas dentro de 24 h, temperatura hace 1h, 2h y 24h y condiciones hace 24h.
Las 3 primeras las debemos introducir obligatoriamente porque son las
variables que indicaremos a Weka que prediga y por tanto debe conocerlas, y las otras 4 se introdujeron porque pensamos que nos podrían dar información extra que
considerábamos importante para la predicción.
3. Filtrado
Una vez hemos terminado de modificar el fichero “a mano” y ya está listo para que Weka trabaje con él, lo abrimos y seguimos preprocesando los datos desde dentro de Weka.
Lo primero que hacemos es eliminar el atributo “precipitación” ya que no tiene ninguna muestra y no nos aporta ninguna información, mediante la opción “Remove” de la pestaña de filtrado en Weka. A continuación nos dedicamos a eliminar las muestras con valores atípicos o erróneos, y para ello nos vamos a la zona de visualización de gráficas de Weka y allí separamos de una manera fácil e intuitiva los datos normales de los claramente erróneos:
En esta imagen se puede ver el proceso de separación de los valores correctos (señalados en el rectángulo gris) de los incorrectos, que toman valores mucho mayores y aislados. Durante este proceso se añade algo de ruido a los datos para poder diferenciar un solo dato aislado de varios que coincidan exactamente en el mismo sitio.
El único problema que tiene hacer esta selección dentro de Weka es que a la vez que elimina las muestras con datos erróneos también elimina aquellas con datos desconocidos, con lo cual no podemos aplicar este método de selección a variables que tengan muchos valores desconocidos (ráfaga, por ejemplo) ya que perderíamos un número demasiado grande de filas que podrían tener valores interesantes en el resto de atributos.
Salvamos los datos ya “limpios” en otro fichero distinto a partir del cual haremos el resto del trabajo.
4. Selección de variables
Bajo la pestaña de select attributes de Weka se han realizado varios análisis para ver qué variables eran más determinantes a la hora de predecir una determinada incógnita. Antes se han eliminado mediante filtros las otras dos incógnitas de manera que no nos influyan.
Para predecir la temperatura en la siguiente hora diferentes algoritmos nos han dado siempre el mismo resultado: lo más importante es siempre la temperatura en el momento actual, y la mayoría de los algoritmos de evaluación de variables no se fijan en ninguna variable más, aunque en mucha menor medida también hemos comprobado que influyen la dirección viento, la temperatura en la hora anterior y 2h antes.
Otra manera de obtener la relevancia de las distintas variables para una predicción es fijándonos en los pesos del algoritmo de regresión lineal. Para ello, en la pestaña Classify de Weka entrenamos un regresor lineal que prediga el valor de la temperatura en la siguiente hora, y observando el valor de los distintos pesos. El resultado obtenido es el siguiente:
Linear Regression Model
temperatura+1h = 0.0066 * anyo + -0.0054 * mes + 0.0018 * dia + -0.0099 * hora + 1.276 * temperatura + 0.0234 * rocio + 0.0134 * humedad + -0.0513 * visibilidad + -0.1881 * dirviento=Norte,Calm,NNE,NE,NO,ENE,ONO,ESE,Variable,SE,Este,Sur,SSO[...]+ -0.3829 * dirviento=Calm,NNE,NE,NO,ENE,ONO,ESE,Variable,SE,Este,Sur,SSO[...] + 0.3205 * dirviento=NNE,NE,NO,ENE,ONO,ESE,Variable,SE,Este,Sur,SSO,SSE,SO[...] + -0.1716 * dirviento=NE,NO,ENE,ONO,ESE,Variable,SE,Este,Sur,SSO,SSE,SO,OSO,[...]+ -0.2136 * dirviento=NO,ENE,ONO,ESE,Variable,SE,Este,Sur,SSO,SSE,SO,OSO,Oeste + 0.0566 * dirviento=ENE,ONO,ESE,Variable,SE,Este,Sur,SSO,SSE,SO,OSO,Oeste + -0.113 * dirviento=ONO,ESE,Variable,SE,Este,Sur,SSO,SSE,SO,OSO,Oeste + 0.2784 * dirviento=ESE,Variable,SE,Este,Sur,SSO,SSE,SO,OSO,Oeste + 0.0289 * dirviento=Variable,SE,Este,Sur,SSO,SSE,SO,OSO,Oeste + -0.1039 * dirviento=SE,Este,Sur,SSO,SSE,SO,OSO,Oeste + -0.165 * dirviento=Sur,SSO,SSE,SO,OSO,Oeste + -0.0308 * dirviento=SSO,SSE,SO,OSO,Oeste + 0.1556 * dirviento=SSE,SO,OSO,Oeste + -0.0839 * dirviento=SO,OSO,Oeste + -0.0772 * dirviento=OSO,Oeste + -0.0188 * velviento + -0.0155 * rafaga + 0.4303 * hechos=Lluvia,Tormenta,Tornado + 1.3874 * hechos=Tormenta,Tornado + -2.6325 * hechos=Tornado +
0.2994 * condiciones=Nublado,Despejado,Tormenta + 0.1557 * condiciones=Despejado,Tormenta + -1.6093 * condiciones=Tormenta + 0.0701 * temperatura-24h + -0.4432 * condiciones-24h=Bruma,Niebla,Lluvia,Nublado,Despejado,Tormenta + -0.2349 * condiciones-24h=Lluvia,Nublado,Despejado,Tormenta + 0.0724 * condiciones-24h=Nublado,Despejado,Tormenta + 0.1522 * condiciones-24h=Despejado,Tormenta + -0.3175 * temperatura-2h + -0.038 * temperatura-1h + -13.1282
De donde podemos deducir que las variables que más influyen en la temperatura de dentro de 1h son las de mayores pesos, es decir, temperatura actual, dirección del viento, hechos, condiciones, condiciones hace 24h y la temperatura de 2h antes.
Para el caso de la temperatura al cabo de 24h, mediante los algoritmos de selección de variables seguimos llegando a la conclusión de que el parámetro más importante es la temperatura actual, mientras que a través de los pesos del regresor lineal observamos lo siguiente:
Linear Regression Model temperatura+24h = -0.0272 * mes + 0.0046 * dia + 0.0299 * hora + 0.7767 * temperatura + -0.0502 * rocio + 0.0342 * humedad + 2.0762 * presion + -0.2565 * visibilidad + -0.2919 * dirviento=Norte,Calm,NNE,NE,ONO,NO,ESE,ENE,Variable,SE,Sur,SSO,[...]+ -1.1679 * dirviento=Calm,NNE,NE,ONO,NO,ESE,ENE,Variable,SE,Sur,SSO,SSE,[...] + 0.6442 * dirviento=NNE,NE,ONO,NO,ESE,ENE,Variable,SE,Sur,SSO,SSE,Este,OSO,[...] + -1.006 * dirviento=ONO,NO,ESE,ENE,Variable,SE,Sur,SSO,SSE,Este,OSO,SO,Oeste + 0.6873 * dirviento=NO,ESE,ENE,Variable,SE,Sur,SSO,SSE,Este,OSO,SO,Oeste + -0.6632 * dirviento=ESE,ENE,Variable,SE,Sur,SSO,SSE,Este,OSO,SO,Oeste + 0.7946 * dirviento=ENE,Variable,SE,Sur,SSO,SSE,Este,OSO,SO,Oeste + -0.3064 * dirviento=Variable,SE,Sur,SSO,SSE,Este,OSO,SO,Oeste + -0.5892 * dirviento=SE,Sur,SSO,SSE,Este,OSO,SO,Oeste + 0.6378 * dirviento=Este,OSO,SO,Oeste + -0.8795 * dirviento=OSO,SO,Oeste + 0.4866 * dirviento=SO,Oeste + -0.8598 * dirviento=Oeste + -0.1389 * velviento + 0.0695 * rafaga + -4.7129 * hechos=Bruma,Lluvia,Tormenta,Tornado + 1.9461 * hechos=Lluvia,Tormenta,Tornado + 1.7919 * hechos=Tormenta,Tornado + 1.7719 * condiciones=Bruma,Niebla,Lluvia,Nublado,Despejado,Tormenta + -0.4326 * condiciones=Niebla,Lluvia,Nublado,Despejado,Tormenta + -0.1768 * condiciones=Nublado,Despejado,Tormenta + 0.3202 * condiciones=Despejado,Tormenta + 0.1323 * temperatura-24h + -1.2203 * condiciones-24h=Bruma,Niebla,Lluvia,Nublado,Despejado,Tormenta + 0.7186 * condiciones-24h=Niebla,Lluvia,Nublado,Despejado,Tormenta + 1.2997 * condiciones-24h=Lluvia,Nublado,Despejado,Tormenta + -0.2585 * condiciones-24h=Nublado,Despejado,Tormenta +
-0.2679 * condiciones-24h=Despejado,Tormenta + 1.6609 * condiciones-24h=Tormenta +
-0.0392 * temperatura-2h + 0.1593 * temperatura-1h + -61.4729
Vemos que se ha incrementado la importancia de los hechos y condiciones actuales así como de las condiciones en las 24h pasadas y la dirección del viento. La relevancia de la presión ha aumentado mientras que la de la temperatura actual ha disminuido bastante. Sin embargo observamos que el error de este regresor lineal es bastante mayor que el del caso anterior (29.2589 % frente a 12.2234 %) por lo cual los resultados son menos fiables.
Para el caso de la predicción de condiciones meteorológicas en 24h no se puede usar el regresor lineal ya que sólo funciona para atributos numéricos, pero a cambio los algoritmos de la pestaña select attributes funcionan mucho mejor,
obteniendo como resultado que los parámetros de los que más depende son: el mes, la humedad, la presión, las condiciones actuales y las temperaturas:
Ranked attributes: 0.0663 8 presion 0.06304 2 mes 0.05468 7 humedad 0.05322 14 condiciones 0.05186 18 temperatura-2h 0.05055 19 temperatura-1h 0.04899 5 temperatura 0.04382 16 temperatura-24h 0.02716 10 dirviento 0.02499 17 condiciones-24h 0.02332 4 hora 0.01993 11 velviento 0.01845 9 visibilidad 0.01488 6 rocio 0.01126 1 anyo 0.00786 3 dia 0.00115 13 hechos 0 12 rafaga
Sin embargo, al final se ha optado por eliminar el menor número de variables posibles ya que se ha pensado que la predicción sería más precisa cuanta más
información se tuviera, de manera que sólo se han eliminado las variables que tienen muy pocas muestras o que son claramente independientes de la variable a predecir según el estudio anterior. De este modo, para la temperatura dentro de 1 h se han eliminado las variables precipitación (eliminada siempre en el preprocesado), año, día, visibilidad y ráfaga, ya que se ha considerado que la temperatura que haga es
ráfaga tiene muy pocos valores conocidos además de parecer también bastante independiente.
Para el caso de predicción de temperatura a 24h se han eliminado las variables día y ráfaga, la primera por ser independiente el número de día del mes de la
temperatura y la segunda por tener pocos datos válidos, tal como en el caso anterior. Por último, para le predicción de las condiciones meteorológicas dentro de 24h se han suprimido las variables de rocío, ráfaga, hechos, visibilidad y día, debido a que son los que peores resultados han obtenido en el estudio realizado anteriormente y por tanto las más independientes de la variable a predecir.
5. Predicción de variables
A la hora de predecir el valor de las variables incógnita, lo primero que debemos hacer es eliminar las otras 2 columnas incógnita, de manera que, por ejemplo, para predecir la temperatura en la siguiente hora no se emplee la temperatura dentro de 24 horas, que es la otra variable incógnita.
A continuación, y dependiendo de si el algoritmo que vamos a ejecutar tiene mucha carga de memoria o de computación, hacemos un submuestreo de los datos mediante un filtro (Resample) aplicado a todas las variables que nos quedan, quedándonos de manera aleatoria con el 20% o el 5% de las muestras según el algoritmo, con lo cual pretendemos aumentar la velocidad de ejecución de los algoritmos y disminuir el riesgo de que Weka finalice su ejecución inesperadamente debido a problemas de memoria.
Bajo la pestaña Classify de Weka será donde realicemos los análisis que nos permitan predecir las variables deseadas mediante diferentes algoritmos. Seleccionamos la opción “Percentage split” que divide automáticamente los datos en 2 grupos: el de evaluación y el de entrenamiento. Es conveniente hacer esto, ya que si evaluáramos el algoritmo sobre los mismos datos con los que lo hemos entrenado los resultados no estarán siendo realistas, ya que corremos riesgo de sobreentrenar el algoritmo haciéndolo demasiado específico.
• Temperatura en la próxima hora:
Se ha intentado predecir la temperatura en la próxima hora usando los siguientes algoritmos: REPtree, KStar, SMOreg, regresión lineal, y tabla de decisión, cuyo funcionamiento ya se explicó en el apartado de introducción.
A continuación se muestran los resultados obtenidos:
Algoritmo Relative Absolute Error Root Mean Square Error
Decision Table 16.5752% 2.1684
RepTree 11.0086% 1.9595
Regresión Lineal 12.2234% 2.1671
KStar 15.4202% 2.7923
SMOreg 12.3167% 2.2720
Podemos ver que el algoritmo que proporciona mejores resultados es el de REPTree, ya que nos da tanto el mínimo error absoluto relativo como el mínimo error cuadrático medio, y además se observa que es el mejor resultado de predicción obtenido para el conjunto de las 3 incógnitas a estimar.
• Temperatura en las próximas 24h
En este caso se han vuelto a aplicar los mismos algoritmos que en el caso anterior, aunque eliminando menos variables a priori ya que al ser un periodo de tiempo más largo la temperatura puede depender en mayor medida de otros factores nuevos.
Los errores obtenidos para cada algoritmo son los siguientes:
Algoritmo Relative Absolute Error Root Mean Square Error Decision Table 26.9804% 4.8446
RepTree 27.9086% 4.8106
Regresión Lineal 29.1446% 4.9389
KStar 29.9598% 5.4625
SMOreg 29.6233% 5.1772
Como se puede ver, en este caso el error obtenido en todos los casos es mayor, ya que es mucho más difícil predecir la temperatura para tiempos más lejanos del actual,
y además se ha comprobado que los algoritmos tardan más en ejecutarse que en el caso anterior al estar usando un mayor número de variables.
El mejor algoritmo para este caso observamos que es el de tabla de decisión, ya que da menor error absoluto, y aunque el mínimo error cuadrático medio corresponde al algoritmo de REPTree, todos los resultados son bastante similares para los algoritmos evaluados.
• Condiciones meteorológicas en las próximas 24h
En este caso se han usado algoritmos distintos ya que estamos prediciendo un atributo no numérico (de clases) y los métodos por lo tanto serán distintos. Los
algoritmos aplicados has sido: Tabla de decisión, J48, SMO, IB1 (K vecinos más próximos) y Reptree, los resultados obtenidos para el error han sido los siguientes:
Algoritmo Relative Absolute Error Root Mean Square Error Decision Table 53.4334% 0.2645
RepTree 59.9942% 0.2715
IB1 70.1764% 0.3479
J48 68.8117% 0.2891
SMO 65.1487% 0.3120
Se puede ver que el algoritmo que nos ofrece menor error es el de la tabla de decisión, aunque en general los resultados obtenidos para esta predicción son bastante malos, teniendo un error relativo considerablemente grande. Posiblemente esto se deba a que estamos tratando con un atributo no numérico y por tanto el error cometido al interpretar una condición cuando en realidad es otra no se evalúa del mismo modo que un atributo numérico.
ANEXO I:
Códigos Java para el preprocesado de datosConcat.java: une los múltiples archivos correspondientes a cada día en uno sólo, cambia el formato de los saltos de línea e introduce la fecha el principio de cada línea:
import java.io.*;
class concat{
// cocatena los archivos de cada dia en uno solo y camia el formato de los saltos de linea
public static void join(File f1,File f2, int i)throws
IOException{
BufferedReader br=new BufferedReader(new FileReader(f2)); BufferedWriter bw=new BufferedWriter(new FileWriter(f1,true)); String line=br.readLine();
String
fecha=((f2.getName()).substring(((f2.getName()).length()-10))).replaceAll("-",",");
while(line!=null){
if (line.equals("")||line.startsWith("<!--"))line=br.readLine();
if(line!=null&&line.startsWith("Hora")&&line.endsWith("<BR>"))li ne=fecha+","+br.readLine();
if(line!=null&&line.endsWith("<BR>"))line=line.substring(0,line. lastIndexOf("<BR>"))+"\r\n
if(line!=null){line=line.replaceAll("<BR>","\r\n"+fecha+","); bw.write(line);} line=br.readLine(); } bw.flush(); bw.close(); }
public static void main(String[] args)throws IOException{
if(args.length!=2){System.out.println("se necesitan dos argumentos: fichero destino y carpeta");return;}
File file=new File(args[0]); File folder=null;
if(args[1].equals(".")){folder=new File("");folder=new
File(folder.getAbsolutePath());}
else folder=new File(args[1]);
if(file.exists()){System.out.println("el fichero destino ya existe y se va a concatenar...");}
File[] files=null;
if(folder.isDirectory())files=folder.listFiles();
else {System.out.println("segundo argumento no es una carpeta"+folder.getAbsolutePath());return;} for(int i=0,j=0;i<files.length;i++)if(files[i].isFile()&&!(files[i].getName()) .equals(file.getName())&&!(files[i].getName()).equals("concat.java")&& !(files[i].getName()).equals("concat.class"))join(file,files[i],j++); } }
Concat3.java: sustituye los datos desconocidos por interrogaciones, elimina líneas sin datos o con horas no válidas
import java.io.*;
class concat3{
//cambia datos desconocidos por interrogaciones y más.
if(args.length!=2) {
System.out.println("se necesitan dos argumentos: fichero origen y destino");
return;
}
File f2=new File(args[0]); File f1=new File(args[1]);
BufferedReader br=new BufferedReader(new FileReader(f2)); BufferedWriter bw=new BufferedWriter(new
FileWriter(f1,true));
String line=br.readLine();
while(line!=null)
{ line=line+"\r\n"; if((line.charAt(line.indexOf(':')+2)!='0')||((line.charAt(line.i ndexOf(':')+1)!='0')&&(line.charAt(line.indexOf(':')+1)!='3')))line=br .readLine()+"\r\n"; if (line.indexOf(",,,,,")!=-1)line=br.readLine()+"\r\n"; line=line.replaceAll("N/A","?"); line=line.replaceAll("-9999.0","?"); line=line.replaceAll("-9999","?"); line=line.replaceAll("-","?"); if(line.endsWith(','))line=line+"?"; if ((line.indexOf(',')!=- 1)&&(line.charAt(line.lastIndexOf(',')-1)==','))line=line.substring(0,line.lastIndexOf(',')).concat("?").conc at(line.substring(line.lastIndexOf(','))); bw.write(line); line=br.readLine(); } bw.flush(); bw.close(); } }
Concat4.java: añade las variables incógnita: temperatura en la siguiente hora, en las siguientes 24h y las condiciones en las próximas 24h.
import java.io.*;
class concat4{
//añade las variables incognita: temp+1, temp+24 y cond+24
public static void main(String[] args)throws IOException{
if(args.length!=2) {
System.out.println("se necesitan dos argumentos: fichero origen y destino");
return;
}
File f2=new File(args[0]); File f1=new File(args[1]);
BufferedReader br=new BufferedReader(new FileReader(f2)); BufferedWriter bw=new BufferedWriter(new
String line[]; line=new String[49];
line[0]=br.readLine();
while((line[0]!=null)&&(line[0].startsWith("@data")==false)) {
bw.write(line[0]+"\r\n"); line[0]=br.readLine();
}
bw.write(line[0]+"\r\n");
for(int i=0;i<49;i++)line[i]=br.readLine();
while(line[48]!=null)
{ if(line[2].charAt(12)==',') { if(line[2].charAt(13)=='?') line[0]=line[0].concat(",?"); else line[0]=line[0].concat(",").concat(line[2].substring(13,line[2]. indexOf(',',14))); } else { if(line[2].charAt(14)=='?') line[0]=line[0].concat(",?"); else line[0]=line[0].concat(",").concat(line[2].substring(14,line[2]. indexOf(',',15))); } if(line[48].charAt(12)==',') { if(line[48].charAt(13)=='?') line[0]=line[0].concat(",?"); else line[0]=line[0].concat(",").concat(line[48].substring(13,line[48 ].indexOf(',',14))); } else { if(line[48].charAt(14)=='?') line[0]=line[0].concat(",?"); else line[0]=line[0].concat(",").concat(line[48].substring(14,line[48 ].indexOf(',',15))); } line[0]=line[0].concat(line[48].substring(line[48].lastIndexOf(" ,"))); bw.write(line[0]+"\r\n");
for(int i=0;i<48;i++)line[i]=line[i+1]; line[48]=br.readLine(); } bw.flush(); bw.close(); } }
Concat7.java: añade las variables extra de temperatura hace 1, 2 y 24h, y condiciones hace 24h.
import java.io.*;
class concat7{
//añade las 4 variables extra, temp-1, temp-2, temp-24 y cond-24
public static void main(String[] args)throws IOException{ if(args.length!=2)
{
System.out.println("se necesitan dos argumentos: fichero origen y destino");
return;
}
File f2=new File(args[0]); File f1=new File(args[1]);
BufferedReader br=new BufferedReader(new FileReader(f2)); BufferedWriter bw=new BufferedWriter(new
FileWriter(f1,true));
String line[];
line=new String[49];
line[0]=br.readLine();
while((line[0]!=null)&&(line[0].startsWith("@data")==false)) {
bw.write(line[0]+"\r\n"); line[0]=br.readLine(); }
bw.write(line[0]+"\r\n");
for(int i=0;i<49;i++)line[i]=br.readLine();
while(line[48]!=null)
{ int i=line[0].indexOf(','); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); line[4]=line[4].concat(line[0].substring(i,line[0].indexOf(',',i +1))); line[2]=line[2].concat(line[0].substring(i,line[0].indexOf(',',i+1))); line[48]=line[48].concat(line[0].substring(i,line[0].indexOf(',',i+1)) ); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); i=line[0].indexOf(',',i+1); line[48]=line[48].concat(line[0].substring(i,line[0].indexOf(',' ,i+1))); bw.write(line[0]+"\r\n"); for(i=0;i<48;i++)line[i]=line[i+1]; line[48]=br.readLine(); } bw.flush(); bw.close(); } }