背景:

有一组30天内的温度与时间的数据,格式如下:

详细情况:共30天的8k+项数据,每天内有260+项,每个记录温度的时间精确到秒

任务就是想根据这样的数据找到规律,来完成给定具体的时间预测出此时的温度

处理思路:先把将数据用时序图表示出来,看看有什么样的规律

代码如下:

import java.awt.Font;
import java.io.BufferedReader;
import java.io.FileReader; import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Day;
import org.jfree.data.time.Hour;
import org.jfree.data.time.Minute; import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset; public class TimeSeriesChart {
ChartPanel frame1;
public TimeSeriesChart(){
XYDataset xydataset = createDataset();
JFreeChart jfreechart = ChartFactory.createTimeSeriesChart("temperature-time", "time", "temperature",xydataset, true, true, true);
XYPlot xyplot = (XYPlot) jfreechart.getPlot();
DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis();
frame1=new ChartPanel(jfreechart,true); //水平底部标题
dateaxis.setLabelFont(new Font("黑体",Font.BOLD,14));
//垂直标题
dateaxis.setTickLabelFont(new Font("宋体",Font.BOLD,12));
//获取柱状
ValueAxis rangeAxis=xyplot.getRangeAxis();
rangeAxis.setLabelFont(new Font("黑体",Font.BOLD,15));
jfreechart.getLegend().setItemFont(new Font("黑体", Font.BOLD, 15));
//设置标题字体
jfreechart.getTitle().setFont(new Font("宋体",Font.BOLD,20)); }
private static XYDataset createDataset()
{
TimeSeries timeseries = new TimeSeries("温度随时间变化图");
String temperature = null;
String time = null;
try
{
BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\lichaoxing\\Desktop\\52001848#2018-07-01-00-00-00_2018-07-31-00-00-00.csv"));
reader.readLine();
String line = null;
//int i = 0;
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");//CSV格式文件为逗号分隔符文件,这里根据逗号切分
temperature = item[2];//这就是你要的数据了
time = item[4];
double value = Double.parseDouble(temperature);//如果是数值,可以转化为数值
time = time.replace("\"", "");
String tmp_split1[] = time.split(" ");
String tmp_split2[] = tmp_split1[0].split("-");
String tmp_split3[] = tmp_split1[1].split(":"); //System.out.println(tmp_split1[0]);
System.out.println(tmp_split1[1]);
Day day = new Day(Integer.valueOf(tmp_split2[2]), Integer.valueOf(tmp_split2[1]), Integer.valueOf(tmp_split2[0]));
Hour hour = new Hour(Integer.valueOf(tmp_split3[0]), day);
Minute minute = new Minute(Integer.valueOf(tmp_split3[1]), hour);
Second second = new Second( Integer.valueOf(tmp_split3[2]) ,minute); timeseries.add(second, value);

//if(i++ > 260)
                  //    break;

            }
reader.close();
}
catch(Exception e)
{
e.printStackTrace();
}
TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();
timeseriescollection.addSeries(timeseries); return timeseriescollection;
}
public ChartPanel getChartPanel()
{
return frame1; }
}
import java.awt.GridLayout;
import javax.swing.JFrame; public class tmp { public static void main(String[] args)throws Exception
{ JFrame frame=new JFrame("统计图");
frame.setLayout(new GridLayout(1,1,10,10));
/*添加折线图*/
frame.add(new TimeSeriesChart().getChartPanel());
frame.setBounds(50, 50, 800, 600);
frame.setVisible(true);
}
}

得到下面的时序图

分析:除了个别异样数据点外,看上去十分平滑,但是并不能具体看到每天的状况,介于每天温度变化基本一致,于是考虑在代码while中,添加提前终止条件(上边注释的代码),观察一天的情况

分析:现在这一天的数据看着就清晰很多了,可以大致认为数据是类正弦的,如果对于精确度要求不高,可以认为它就是一个具有周期的数据

于是考虑将含有一个谷底(极小值)的一段作为周期的一个,可以近似看作是二次函数,那现在就来拟合这个二次函数,拟合采用多项式拟合

方法就是:根据局部极小值连续出现两次求解周期(这两次的值及可能不同,不过也无所谓,只是用其来大概计算周期)

代码如下:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.Date; import org.apache.commons.math3.fitting.PolynomialCurveFitter;
import org.apache.commons.math3.fitting.WeightedObservedPoints; public class predict_temperature
{ private static String[] observed_data(double flag, BufferedReader reader) throws Exception
{
String line = null;
String[] i_want = new String[4];
if(flag > 0)
{
double tmp = 1000;
System.out.println(flag);
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");
double value = Double.parseDouble(item[2]);
if(value <= tmp)
tmp = value;
else
{
i_want[0] = item[0];
i_want[1] = item[4].replace("\"", "");
break;
}
}
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");
double value = Double.parseDouble(item[2]);
if(value >= tmp)
tmp = value;
else
break;
}
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");
double value = Double.parseDouble(item[2]);
if(value <= tmp)
tmp = value;
else
{
i_want[2] = item[0];
i_want[3] = item[4].replace("\"", "");
break;
}
}
}
else
{
double tmp = -1000;
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");
double value = Double.parseDouble(item[2]);
if(value >= tmp)
tmp = value;
else
{
i_want[0] = item[0];
i_want[1] = item[4].replace("\"", "");
break;
}
}
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");
double value = Double.parseDouble(item[2]);
if(value <= tmp)
tmp = value;
else
break;
}
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");
double value = Double.parseDouble(item[2]);
if(value >= tmp)
tmp = value;
else
{
i_want[2] = item[0];
i_want[3] = item[4].replace("\"", "");
break;
}
}
}
return i_want; } public static void main(String[] args) throws Exception
{ WeightedObservedPoints points = new WeightedObservedPoints(); String input_time = args[1] + " " + args[2];
File file = new File(args[0]);
double time_diff = 0; BufferedReader reader = new BufferedReader(new FileReader(file));
reader.readLine();
reader.mark((int)file.length()); /*计算周期*/
double compare_item1 = Double.parseDouble(reader.readLine().split(",")[2]);
double compare_item2 = Double.parseDouble(reader.readLine().split(",")[2]);
String[] cycle_result = new String[4];
cycle_result = observed_data(compare_item1 - compare_item2, reader);
int start_num = Integer.parseInt(cycle_result[0]);
int end_num = Integer.parseInt(cycle_result[2]);
SimpleDateFormat tmp_day = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date start_now = tmp_day.parse(cycle_result[1]);
Date end_now = tmp_day.parse(cycle_result[3]);
/*计算周期*/
int cycle = end_num - start_num;
reader.reset();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat input_time_format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date input_time_ = input_time_format.parse(input_time);
Date start_time = null;
int i = 0;
String line = null;
String time = null;
while((line=reader.readLine())!=null)
{
String item[] = line.split(",");
time = item[4];
double value = Double.parseDouble(item[2]);
time = time.replace("\"", "");
Date now = sdf.parse(time);
if(i == 0)
start_time = now;
double offset = (now.getTime() - start_time.getTime());
points.add(offset, value);
time_diff = (input_time_.getTime() - start_time.getTime()) % (end_now.getTime() - start_now.getTime());
if(i++ > cycle)
break; }
PolynomialCurveFitter fitter = PolynomialCurveFitter.create(2);
double[] result = fitter.fit(points.toList()); double result_time = result[2] * time_diff * time_diff + result[1]* time_diff + result[0];
System.out.println(result_time);
reader.close();
}
}

这里我要解释一下  observed_data   方法

由于数据开始不知道是递增还是递减,可以先读取两个连续的温度用于判断此时是增还是减,就是下面这两行代码

double compare_item1 = Double.parseDouble(reader.readLine().split(",")[2]);
double compare_item2 = Double.parseDouble(reader.readLine().split(",")[2]);

我这里的找周期方法思路很简单,就是先找到一个局部最低(高)点,记录此时的序号与时间

再继续沿着线向前走,下一个拐点肯定是局部最高(低)点,此时它是中间点,什么都不做

再继续的话,又到了一个局部最低(高)点,记录此时的序号与时间

现在:计算两次记录的差值,便可以知道周期点的个数,以及周期时间

对于预测,当然就可以根据预测时间与一天的起始时间差值模周期时间将其映射到第一个周期内,将余数代数拟合函数,求解近似值

到这,就可以预测温度了,比如配置时间参数

观测的真实值是:

预测结果为:

可以看出,结果还算可以(不过有些时间点的数据误差有在1-2之间的)


本节完......

[java] 数据处理的更多相关文章

  1. Java数据处理

    对于形如“(TYPE=SITA##)&&(((CTYP=FPL##)||(CTYP=CHG##)||(CTYP=CNL##)||(CTYP=DLA##)||(CTYP=DL##)||( ...

  2. JAVA数据处理的常用技术

    背景 在实际开发中,数据的处理有五种:获取.传输.存储.分析.转换.每种各对应一些常用的技术. 序列化和反序列化 序列化是将对象的信息转换为可传输或可存储形式的过程.反序列化就是反过来让这些可传输的. ...

  3. Java数据处理,Map中数据转double并取小数点后两位

    BigDecimal order = (BigDecimal) map.get("finishrat"); double d = (order == null ? 0 : orde ...

  4. Java架构师之路 Spring学习笔记(一) Spring介绍

    前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...

  5. Java编程实战宝典PDF (中文版带书签)

    Java编程实战宝典PDF 目录 第1篇 Java基础知识入门第1章 Java的开发运行环境( 教学视频:57分钟)1.1 Java运行原理与Java虚拟机1.1.1 Java运行原理简述1.1.2 ...

  6. Spring框架快速入门之简介

    Spring是java平台上的一个开源应用框架.它的第一个版本是由Rod Johnson写出来的.Rod在他的Expert One-On- One Java EE Design and Develop ...

  7. 转:eval(data)和eval("("+data+")")

    http://www.w3school.com.cn/jsref/jsref_eval.asp JavaScript eval() 函数:eval() 函数可计算某个字符串,并执行其中的的 JavaS ...

  8. Hadoop MapReduce编程 API入门系列之Crime数据分析(二十五)(未完)

    不多说,直接上代码. 一共12列,我们只需提取有用的列:第二列(犯罪类型).第四列(一周的哪一天).第五列(具体时间)和第七列(犯罪场所). 思路分析 基于项目的需求,我们通过以下几步完成: 1.首先 ...

  9. Spring学习【Spring概述】

    从本文開始,我们就要一起学习Spring框架,首先不得不说Spring框架是一个优秀的开源框架. 当中採用IoC原理实现的基于Java Beans的配置管理和AOP的思想都是非常值得学习与使用的.以下 ...

随机推荐

  1. Problem C: 多线程 解题报告

    Problem C: 多线程 Description 多线程是一种常见的加速手段,利用多个线程同时处理不同的任务可以一定程度上减少总耗时,达到提高效率的目的.然而,多个线程间的执行顺序是完全不可控的, ...

  2. 内置函数enumerate()

    enumerate是枚举的意思,顾名思义,enumerate()函数用来将一个可迭代序列生成一个enumerate对象,该enumerate对象的每个元素是由可迭代对象的索引编号和对应的元素组成的元祖 ...

  3. Codeforces Round #541

    因为这次难得不在十点半(或是更晚),大家都在打,然后我又双叒叕垫底了=.= 自己对时间的分配,做题的方法和心态还是太蒻了,写的时候经常写一半推倒重来.还有也许不是自己写不出来,而是在开始写之前就觉得自 ...

  4. 8.30 牛客OI赛制测试赛1 F题 子序列

    题目描述 给出一个长度为n的序列,你需要计算出所有长度为k的子序列中,除最大最小数之外所有数的乘积相乘的结果 输入描述: 第一行一个整数T,表示数据组数.对于每组数据,第一行两个整数N,k,含义如题所 ...

  5. HDU 6085 bitset

    Rikka with Candies Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  6. python实现windows Service服务程序

    python实现windows Service服务程序 win32serviceutil.ServiceFramework是封装得很好的Windows服务框架,本文通过继承它来实现. 通过SvcDoR ...

  7. Vue自定义组件插入值

    我们自定义组件的时候有时候需要往组件里面插一些内容: //定义一个组件test,插值内容用slog来代替 export default { name: 'test', template:` <d ...

  8. AngularJs分层结构小demo

    后端mvc分层,前端也要分层才对嘛.分层的好处不言而喻.简直太清晰,容易维护.反正清爽的一逼.不信你看. 思路:分为controller层和service层.controller层再提取一个公共的层. ...

  9. SQL记录-PLSQL异常

    PL/SQL异常   程序执行过程中出现错误情况被称为在PL/SQL异常. PL/SQL支持程序员在程序中使用异常块捕获这样的条件并采取适当的动作应对错误情况.有两种类型的异常: 系统定义的异常 用户 ...

  10. bzoj千题计划184:bzoj1261: [SCOI2006]zh_tree

    http://www.lydsy.com/JudgeOnline/problem.php?id=1261 dp[l][r][dep]  区间[l,r]内的节点,根在dep层的最小代价 枚举根i,dp[ ...