pablofrommars / ggnet Goto Github PK
View Code? Open in Web Editor NEWGG.Net Data Visualization
Home Page: https://pablofrommars.github.io
License: MIT License
GG.Net Data Visualization
Home Page: https://pablofrommars.github.io
License: MIT License
CSS requires numbers using dots (instead of commas). The code just uses standard number to string conversions (implicitly ToString ()) without setting any culture Information. Therefore the svgs generated do not work, when cultures are used which have numbers using commas instead of dots. E.g. style="width: 578,15" instead of corretly generating "width: 578.15"
I've done all the nessecary work on my local repository, but can't create a pull request on your project. Let me know the way in case I should share the code with your project.
Hi, I was testing your component but was not able to change the geom type depending on what type of chart the user has selected. When I refresh the page (F5) the the data is shown correctly. This is the code I use for selecting the geom:
switch (ChartType)
{
case 1:
reportData = Plot.New(reportSource, x: pX, o => o.Value)
.Geom_Bar(position: PositionAdjustment.Dodge)
.Scale_X_Discrete(expand: (0.0, 0.1, 0, 0.1), formatter: labeller)
.Scale_Fill_Discrete(o => o.Id, Colors.Brewer.YlGnBu[4], direction: -1)
.YLab("y label%")
.XLab("Parameters")
.Title("Test report")
.Theme(dark: false);
break;
default:
reportData = Plot.New(reportSource, x: pX, o => o.Value)
.Geom_Bar(position: PositionAdjustment.Stack)
.Scale_X_Discrete(expand: (0.0, 0.1, 0, 0.1), formatter: labeller)
.Scale_Fill_Discrete(o => o.Id, Colors.Brewer.YlGnBu[4], direction: -1)
.YLab("y label%")
.XLab("Parameters")
.Title("Test report")
.Theme(dark: false);
break;
}
Hey Pablo, thanks for creating this project. It's really promising for my use case. I'm creating a pain chart for physical therapy patients. I started from the SPY example and got this far:
data = Plot.New(source, x: o => o.When, y: o => o.Pain)
.Title("Pain Over Time")
.Geom_Area(alpha: 0.3)
.Geom_VLine(x: o => string.IsNullOrWhiteSpace(o.Activity) ? default : o.When,
color: "#FF00D9",
lineType: LineType.Dashed)
.YLab("Level")
.XLab("Date")
.YLim(min: 0, max: 10)
.Caption("Source: Patient")
.Theme(theme);
One key difference for me is I am using LocalDateTime
instead of just LocalDate
.
My questions are
I found a solution to some of my questions by Googling for ggplot, but not all solutions seem to map to ggnet. It's much harder to Google for ggnet, so here I am.
Thanks!
Thank you for the work you have done in GGNet. My co-worker and I are trying to implement a map of the United States divided into states. We’re looking for a way to implement this, but we can’t seem to find out how the GGNet library draws the countries. Is it possible to do this? Please get back to us when convenient for you.
Hi!
I'm trying to achieve a specific effect where the areas in an area chart are emphasized with a line. I believe this improves clarity. (See * below for a good example, if you have this book)
To achieve this effect, I added both a Geom_Area
and a Geom_Line
to the plot. It works!
However, two things occur, as you can see in the bottom chart:
I tried to discover a way to color a series but without having any labels but it doesn't seem possible at the moment.
data = Plot.New(source, x: o => o.Milliseconds, y: o => o.Value)
.Geom_Line(source, width: 1, x: o => o.Milliseconds, y: o => o.Value)
.Geom_Area(alpha: 0.3, x: o => o.Milliseconds, y: o => o.Value)
.XLab(XLabel)
.YLab(YLabel)
.Scale_X_Continuous(formatter: MillisecondsFormatter.Instance)
.Scale_Y_Continuous(limits: (0, maxValue), format: YLabelFormat)
.Scale_Fill_Discrete(o => o.Series, Colors.Viridis)
// Need this to get the lines, but I don't want the additional labels :)
.Scale_Color_Discrete(o => o.Series, Colors.Viridis)
.Theme(dark: false, legend: Position.Right);
(*) Data Visualization (Kieran Healy) page 88, fig 4.18
I'm having a chart with long labels. So as they are (very) long the text can't be read as the text is overlapping.
It would be great to have an option to rotate the text labels by (at least) a certain degree (e.g. 45° or 90°). I'm not an expert in svg, but it seems this could be done in Panel.razor by adding a transform attribute to the text object. Maybe it would be also possible to add this to the style definitions in Plot.razor.
Thanks
If LocalDateTime
is used for x-axis function Train
In DateTimePosition
does expect the data to come in ordered already (oldest to youngest). Also in case more than one panel is used the first panel has to start with the oldest data. Otherwise those data will not be shown.
I replaced …
var current = values[values.Count - 1];
if (current.Date == key.Date)
{
current = current.Plus(sampling);
while(current <= key)
{
values.Add(current);
current = current.Plus(sampling);
}
}
else
{
values.Add(key);
}
… with …
for (var pos = values[0].Minus (sampling); pos >= min; pos = pos.Minus (sampling))
{
values.Add (pos);
}
for (var pos = values[values.Count - 1].Plus (sampling); pos <= max; pos = pos.Plus (sampling))
{
values.Add (pos);
}
feel free to use it.
When I build my Blazor WASM app with GGNet, a file called _content/GGNet/pixelWidthCalculator.html
is added. What is it for, and if it is not used is there a way to remove it?
I tried to find a way to create a chart which shows values for the last 2 hours. I guess I should use the expand
fields of Scale_X_Discrete_DateTime
past2hPlot = Plot.New (callers.Values.Where (c => c.StartTimeOffset > minLimit),
x: o =>
{
var dto = o.StartTimeOffset;
return LocalDateTime.FromDateTime (dto.AddSeconds (-dto.Second).ToLocalTime ().DateTime);
},
y: o => 1.0)
.Geom_Bar (position: PositionAdjustment.Stack, width: 0.5)
.Scale_X_Discrete_DateTime (expand: (0.0, 0.1, 0, 0.1))
.Scale_Fill_Discrete (o => o.Lang ?? String.Empty, Colors.Viridis, direction: -1)
//.Facet_Wrap (selector: o => o.label, freeY: true)
.XLab ("Anrufer")
.Theme (dark: false, legend: Position.Bottom);
Nevertheless it looks like the Set
function in class DateTimePosition
which calls SetRange
function is based on doubles instead of some sort of time values.
Also from what I see from code the calculation of minimum and maximum of the limits
fields in Scale_X_Discrete_DateTime
used in Set
function does only work for limits which are present in the source set itself. If a limit is specified which is not included in the source set all data will be shown in the chart ignoring any limits. There should be a less or greater than comparission form my point of view.
It's not an issue, but a question.
The following setup (taking from samples) throws a NullReferenceException
map = Plot.New (data)
.Geom_Map (o => o.country.Polygons, tooltip: o => (o.country.Capital.Point, o.country.Name), alpha: 0.7, width: 0.2, animation: true)
.Scale_Longitude (limits: (-15, 30))
.Scale_Latitude (limits: (30, 70))
.Scale_Fill_Continuous (o => o.count, Colors.Viridis, name: "count")
.Theme (theme);
in Set
function in class Fill.cs
, because Wilkinson.extended returns null if limits.min is equal to limits.max. This seams to be the case if all data supplied to Plot.New have the same value of count
.
var extended = Wilkinson.extended(limits.min, limits.max, m);
var labels = new (string value, string label)[extended.Length];
And Wilkinson.extended returns null because of this code
if (dmax - dmin < eps)
{
//return(seq(from=dmin, to=dmax, length.out=m))
return null;
}
Love your library and I'm successfully using it for some charts. Now I ran into a problem.
A line chart with X axis defined as Scale_X_DateTime_Discrete
will fault if the data points have X values with subminute resolution (i.e. with a 'seconds' part in the DateTime).
Using the following:
"Metrics": [
{
"Timestamp": "2020-04-30T13:30:00+02:00",
"Series": "broker",
"Value": "10"
},
{
"Timestamp": "2020-04-30T15:30:05+02:00",
"Series": "broker",
"Value": "40"
},
{
"Timestamp": "2020-05-01T15:50:10+02:00",
"Series": "broker",
"Value": "50"
}
],
Will cause output errors like the following in the console:
Error: <line> attribute x1: Expected length, "NaN".
Error: <path> attribute d: Expected number, "M NaN 123.80198019…".
When I set the Seconds part to 0, the chart renders OK.
My code (experimented with limits to no avail):
data = Plot.New(source, x: o => o.Timestamp, y: o => o.Value)
.Geom_Line(source, width: 2, x: o => o.Timestamp, y: o => o.Value)
.XLab("Timestamp")
.YLab("Value")
//.Scale_X_Discrete_DateTime(limits: limits)
.Scale_Y_Continuous(limits: (0, maxQueueLength))
.Scale_Color_Discrete(o => o.Series, Colors.Viridis )
.Theme(dark:false, legend: Position.Bottom)
Unfortunately, my time series have timespans of once per second over 10 minutes.
It would be great if expand_limits could be implemented. I want to show a certain range in a chart even if values would not need such a "wide" range. For example expand_limits with a range of 0 to 1, even all values are in a range from 0.3 to 0.7
Hi Pablo,
@pablofrommars, I have downloaded project to test in local and examples are not working. It's same with your wensite https://pablofrommars.github.io/
I have seen your example project is a blazor wasm project, Can your project work on blazor server side project?
tia!
P.s. Project sounds interesting.
Are there any plans to implement a BoxPlot to accompany those Violin plots. It would be mighty useful.
Hi, any Roadmap for piecharts?
If a chart should show positive values only, but the max limits is unknown and should not be set, the chart shows a range of -0,05 to +0,05 if data values are 0.
The reason is
SetRange(Limits.min ?? _min ?? 0.0, Limits.max ?? _max ?? 0.0);
in function Set
of class Extended
and the implementation of SetRange
in class Position
if (min == max)
{
Range = (
min - 0.05,
max + 0.05
);
}
While rending data an System.NullReferenceException in Data/Data.cs line 409 is thrown.
for (int g = 0; g < panel.Geoms.Count; g++)
stack trace
GGNet.dll!GGNet.Data<(Helper.Database.Models.DbTask.Types, Helper.Database.Models.TaskHistory.States, string, double?), Helper.Database.Models.DbTask.Types, double>.RunLegend(bool first) Zeile 409 C#
GGNet.dll!GGNet.Data<(Helper.Database.Models.DbTask.Types, Helper.Database.Models.TaskHistory.States, string, double?), Helper.Database.Models.DbTask.Types, double>.Render(bool first) Zeile 446 C#
GGNet.dll!GGNet.Components.Plot<(Helper.Database.Models.DbTask.Types, Helper.Database.Models.TaskHistory.States, string, double?), Helper.Database.Models.DbTask.Types, double>.Render(bool firstRender) Zeile 37 C#
GGNet.dll!GGNet.Components.Plot<(Helper.Database.Models.DbTask.Types, Helper.Database.Models.TaskHistory.States, string, double?), Helper.Database.Models.DbTask.Types, double>.OnInitialized() Zeile 32 C#
[Externer Code]
The exception is thrown because panel == NULL. I guess the cause for this is an empty data source (groupTasks) for the following setup
tasksPlot = Plot.New (groupTasks, x: o => o.typ, y: o => o.data ?? 0)
.Geom_Bar (position: PositionAdjustment.Dodge, width: 0.5, tooltip: o => Math.Round (o.data ?? 0, 2).ToString ())
.Scale_X_Discrete (expand: (0.0, 0.1, 0, 0.1), formatter: labeller)
.Scale_Fill_Discrete (o => o.state, Colors.Viridis, direction: -1)
.Facet_Wrap (selector: o => o.label, freeY: true)
.XLab ("kind of task")
.Theme (dark: false, legend: Position.Bottom);
While obviously it's discussable if an empty data source makes sense, from my point of view it should generate an empty chart and at least should not "crash" on rending, but rather throw an exception on setup (if the prefered option (an empty chart) is not the way to go)
As shown on https://pablofrommars.github.io/examples/choropleth the max value of the Guid.ColorBar legend is not placed at the left position of the color bar. From the example it was not clear if just the very left number is missing (or missing by design), but the placements match the colors. But after drawing such a country map it's clear that the numbers placed above the color are the min and max values used in the chart and no additional number are missing on the left side, but the position of the numbers do not match the respective color of the ColorBar shown below.
The max value (in the example above 80) should be places at the very beginning (left side) of the ColorBar, while the min value should stay were it is currently. All values in between should move accordingly to match their colors show on the map.
The x position and width will not be calulated correctly for charts having more than 1 entry per minute in the their source set. The x position will be NaN (as well as the width) resulting in not showing any information in the chart.
class DateTimePosition
returns double.NaN when a value (on x-axis) cannot be found. Which in fact should not happen, but …
public override double Map(LocalDateTime key)
{
var index = values.IndexOf(key);
if (index < 0)
{
return double.NaN;
}
return index;
}
… the function Train
will skip to add entries in case the sampling rate is less than one minute.
public override void Train(LocalDateTime key)
{
if (values.Count > 0)
...
var current = values[values.Count - 1];
if (current.Date == key.Date)
{
current = current.Plus(sampling);
while(current <= key)
{
values.Add(current);
current = current.Plus(sampling);
}
}
The way it's currently setup also leads to problems if samples have different minutes, but are in the range of less than 60 seconds. What was the reason to use a "sampling frequency" here? My expectation would be to remove this "sampling" completly, as I want to display data within a period of 1 minute. Anyway if sampling is used here to combine entries (what ever that would mean) the lookup function Map
should handle that correctly.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.