我正在使用Flex绘制时间序列数据。数据范围是从2002年到2009年,但数据在某些时间段(即从2004年4月到2005年8月)不可用。以下行显示了我用于图表的标签:
<mx:Canvas id="cp" backgroundColor="#ffffff" fontFamily="Verdana" fontSize="12" color="#093A89" fontWeight="bold" width="100%" height="100%" alpha="1" creationComplete="init()">
<mx:LineChart id="cChart" showDataTips="true" paddingRight="40" paddingLeft="30" width="100%" height="85%">
<mx:verticalAxis>
<mx:LinearAxis id="linearAxis" baseAtZero="false" title="{parameterLabel}" minorInterval="0.5" interval="1.0"/>
</mx:verticalAxis>
<mx:verticalAxisRenderers>
<mx:AxisRenderer axis="{linearAxis}" fontSize="10">
<mx:axisStroke>
<mx:SolidColorStroke weight="6" color="#BBCCDD" alpha="1" caps="square"/>
</mx:axisStroke>
</mx:AxisRenderer>
</mx:verticalAxisRenderers>
<mx:horizontalAxis>
<mx:DateTimeAxis id="ca" minimum="{sDate}" maximum="{eDate}" title="Date" dataUnits="days" dataInterval="1" labelUnits="days"/>
</mx:horizontalAxis>
<mx:horizontalAxisRenderers>
<mx:AxisRenderer axis="{ca}" canDropLabels="true" fontSize="10" labelRotation="45">
<mx:axisStroke>
<mx:SolidColorStroke weight="6" color="#BBCCDD" alpha="1" caps="square"/>
</mx:axisStroke>
</mx:AxisRenderer>
</mx:horizontalAxisRenderers>
<mx:series>
<mx:LineSeries id="l1" visible="false"/>
</mx:series>
</mx:LineChart>
<mx:Legend id="mylgn" horizontalCenter="0" bottom="32"/>
<s:Label id="lblChart1" text="{dataType} {parameterLabel} at {streamLabel}" horizontalCenter="0" bottom="20"/>
<s:Label id="lblChart2" text="{optionalText}" horizontalCenter="0" bottom="5"/>
下图说明了上述代码创建的图表:
正如您所看到的,没有数据的间隔存在间隙。有没有办法删除/削减没有数据的间隔?这类数据的最佳做法是什么?
非常感谢任何想法或建议
答案 0 :(得分:1)
这是通过适配器到dataProvider
。
要显示缺失样本之间的水平线,您必须向数据提供者添加一个额外的样本,其值等于最后一个样本。
如果你有时间序列数据:
timestamp value
4/2004 3
8/2005 23
您可以在8/2005之前立即添加一个等于上一个值3的附加样本。
timestamp value
4/2004 3
7/2005 3 <-- insert sample
8/2005 23
不是在值3和23之间插值,而是显示平坦的水平线。
示例数据模型
package
{
public class TrendData
{
public var timestamp:Date;
public var value:Number;
}
}
静态适配器实用程序
package
{
import mx.collections.ArrayList;
public class TimeSeriesDataAdapter
{
public static function interpolate(data:ArrayList):ArrayList
{
var set:ArrayList = new ArrayList();
var timespan:Number;
// add first sample:
set.addItem(data[0]);
for (var i:uint = 1; i < data.length; i++)
{
// measure timestamp between current sample and last sample
timespan = TrendData(data[i]).timestamp.time - TrendData(data[i-1]).timestamp.time;
// if the timespan is greater than desired range (1-day), add a sample
if(timespan >= 86400000)
{
var trendData:TrendData = new TrendData();
// set timestamp just before sample
trendData.timestamp = new Date(TrendData(data[i]).timestamp.time - 1);
// set value to previous value
trendData.value = TrendData(data[i-1]).value;
set.addItem(trendData);
}
set.addItem(data[i]);
}
return set;
}
}
}
数据可视化实施
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
[Bindable]
[ArrayElementType("TrendData")]
public var data:ArrayList
]]>
</fx:Script>
<mx:LineChart dataProvider="{TimeSeriesDataAdapter.interpolate(data)}" />
</s:Application>
答案 1 :(得分:0)
我用Jason的答案修复了我的图表中的差距问题。但是,为了使代码适合我的应用程序,我应用了以下更改。 1-我将ArryList替换为ArrayCollection 2-我没有使用TrendData类 3-由于我的日期归档是字符串,我必须先将其转换为日期 4-我认为7天或更长时间是一个差距 5-在创建过多的点之前,我必须对ArrayCollection进行排序。
以下显示了我的TimeSeriesDataAdapter.interpolate函数版本:
public static function interpolate(data:ArrayCollection):ArrayCollection
{
var set:ArrayCollection = new ArrayCollection();
var timespan:Number;
var oneDayTime:Number = 86400000; // 1000*60*60*24 = 1 day
for (var j:uint = 1; j < data.length; j++)
{
// measure timestamp between current sample and last sample
data[j].formattedDate = DateField.stringToDate(data[j].Date,"MM/DD/YYYY");
data[j].time = data[j].formattedDate.time;
}
var dataSortField:SortField = new SortField();
dataSortField.name = "time";
var numericDataSort:Sort = new Sort();
numericDataSort.fields = [dataSortField];
data.sort = numericDataSort;
data.refresh();
// add first sample:
set.addItem(data[0]);
for (var i:uint = 1; i < data.length; i++)
{
// measure timestamp between current sample and last sample
timespan = data[i].time - data[i-1].time;
// if the timespan is greater than desired range (7-days), add a sample
if(timespan >= oneDayTime*7)
{
var trendData:Object = new Object();
var timestamp:Date = new Date();
trendData = data[i-1];
// set timestamp just before sample
timestamp.time = data[i].time - 1;
trendData.Date = DateField.dateToString(timestamp,"MM/DD/YYYY");
set.addItem(trendData);
}
set.addItem(data[i]);
}
return set;
}