如何在Flex中没有数据时删除时间序列数据图表中的间隙?

时间:2012-07-05 23:08:04

标签: flex charts time-series timeserieschart

我正在使用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"/>

下图说明了上述代码创建的图表: enter image description here

正如您所看到的,没有数据的间隔存在间隙。有没有办法删除/削减没有数据的间隔?这类数据的最佳做法是什么?

非常感谢任何想法或建议

2 个答案:

答案 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;
 }