Although there are lots of visualization technics, the treemap chart is a good way to visualize hierarchical data. Let’s say you have the following table:
Category
Name
Count
Warning
Temperature increased
30
Disk space is low
20
Security Issue
Intrusion detected
5
Information
Print job completed
10
Create a WinForm project and place an UltraWinChart control onto it. Change the chart type to TreeMap and we’re ready to go.
The above table could be represented with the following function in VB.NET:
Private Function GetData() As DataTable
Dim returnValue As New DataTable()
With returnValue
With .Columns
.Add("Category", GetType(String))
.Add("Name", GetType(String))
.Add("Count", GetType(Double))
End With
With .Rows
.Add(New Object() {"Warning", "Temperature increased", 30})
.Add(New Object() {"Warning", "Disk space is low", 20})
.Add(New Object() {"Security Issue", "Intrusion detected", 5})
.Add(New Object() {"Information", "Print job completed.", 10})
.AcceptChanges()
Return returnValue
End Function
And, in Form load event we could use this as the datasource:
Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
With Me.UltraChart1
'Set the Data Source of the chart
With .Data
.DataSource = GetData()
.DataBind()
End Sub
Assuming you have a TreeMap chart on Form, the result will be the following:
<see picture in attached document>
So far, so good. We can see all the values. But let’s change the values… For example, let “Print job completed” be 20,000.
.Add(New Object() {"Information", "Print job completed.", 20000})
In this case the treemap chart will output the following:
Where are the other categories? Actually it was rendered but since the difference between them is too large, they are not visible.
Other chart types have logarithmic scales but TreeMap is not one of them! Rest of this article will show you how to visualize that kind of data with TreeMap correctly.
Using the following function will transform the values into logarithmic scale:
Private Function TransformData(input As DataTable) As DataTable
For Each dr As DataRow In input.Rows
dr("Count") = Math.Log10(dr("Count"))
Next
Return input
And the form_load will be like this:
'Get the dummy data
ChartData = GetData()
With Me.UltraChart2
.DataSource = TransformData(ChartData)
When we run the application, it will output this result:
Looks like we’ve done it! But wait… what about the tooltips? Mouse over “Print job completed” and the toolti will display 04.3!
What is 04.3? Well, it is Log10 of 20,000 of course! Hmm… what about categories? Mouse over “Warning” and the tooltip will display 2.78 (sum of “Temperature increased” + “Disk space is low”). This introduces another challenge… Changing the tooltips to display correct values. But this is a little harder than you might think.
In order to display custom tooltips, you need to implement an interface called “IRenderLabel.” The following code snippet is an example:
Private Class MyLabelRenderer
Implements Infragistics.UltraChart.Resources.IRenderLabel
Public Overloads Function ToString(
ByVal context As System.Collections.Hashtable) As String Implements
Infragistics.UltraChart.Resources.IRenderLabel.ToString
'Return the custom string here
Return "This is a custom tooltip"
End Class
In order to utilize this interface, we must tell Ultrachart to change the way it generates the tooltips. This is done as follows:
Dim myLabelHashTable As New Hashtable()
myLabelHashTable.Add("MyLabel", New MyLabelRenderer(ChartData))
'Attach the Hash table to the Chart
.LabelHash = myLabelHashTable
'Assign the custom label to the ToolTip
With .Tooltips
.Format = Infragistics.UltraChart.[Shared].Styles.TooltipStyle.Custom
.FormatString = "<MyLabel>"
When you run the application, the following will be shown when you mouse over chart tiles:
Well, it worked but it is useless at this point.
In order to access data values and labels we can use the hashtable interface uses. Change MyLabelRenderer class so that it will look like this:
Private ReadOnly data As DataTable
Public Sub New(ByVal chartData As DataTable)
data = chartData
'The ToString method will take the custom label <MyLabel> and
'return the string to display in the control.
ByVal context As System.Collections.Hashtable) As String
Implements Infragistics.UltraChart.Resources.IRenderLabel.ToString
Dim seriesLabel As String = context("SERIES_LABEL")
Dim itemLabel As String = context("ITEM_LABEL")
Dim dataValue As Double = context("DATA_VALUE")
'Return the string
Return String.Format("series_label: {0}" & vbCrLf &
"item_label: {1}" & vbCrLf &
"data_value: {2}",
seriesLabel, itemLabel,
Math.Pow(10, dataValue).ToString("#,#"))
And run the application. The tooltips will look (like) correct now:
But wait, what happens when you mouse over Warning category? It will display 600! Which is not the sum of 20+30! In order to solve this problem, we need to go back to Math101: Sum of Logarithmic values!
LOG10(20) + LOG10(30) = 2.778
But
POWER10(2.778) = 600
You need to add them up one by one. Maybe there is a better way but my Math 101 knowledge is 20 years old! J
If you take a close look at the constructor of the MyLabelRenderer class, you’ll notice we pass a datatable into it. Using the datatable, we can access the correct values. Here is the final code to display everything correctly:
Private ReadOnly ht As New Hashtable
For Each dr As DataRow In data.Rows
ht(dr("Name").ToString) = dr("Category").ToString
ByVal context As
System.Collections.Hashtable) As String Implements
If ht.ContainsKey(itemLabel) Then
'we have a leaf node
"item_label: {1}" & vbCrLf & "data_value: {2}",
Else
'we have a category
Dim total As Double = 0.0
For Each dr As DataRow In data.Select("Category='" & itemLabel & "'")
total += Math.Pow(10, dr("Count"))
seriesLabel, itemLabel, total.ToString("#,#"))
End If
This article is not a general purpose solution. Using aifferent data shape might need additional steps. Also, I'd like to thank Georgi of Infragistics who helped me a lot to understand techniques mentioned in this article. Lastly, I could not upload pictures / format code since the website does not allow me but attached you'll find the entire article in Word format.
Great article !!! Thanks for sharing and feedback
and the solution file is attached...