I have used CCC Heat Grid in CDE to create a bubble chart with bubbles of different colors. My data set has only 6 values: (1, 1.1, 2, 2.1, 3, 3.1). I have sizeRole property to "value" so that the size of the bubble varies based on the magnitude of these six values. Alternative, I could have set colorRole property to "value". I have set three colors: green (1), yellow (2) and red (3).
Now, what I want to have 1 as green, 2 as yellow and 3 as red; and biggest constant size for 1.1, 2.1 and 3.1. The values 1.1, 2.1 and 3.1 represent alarms in my data set, so I want them to be of biggest size bubble or some other differentiating visual element.
I tried the following in pre-execution but no luck
function changeBubbles(){
var cccOptions = this.chartDefinition;
// For changing extension points, a little more work is required:
var eps = Dashboards.propertiesArrayToObject(cccOptions.extensionPoints);
// add extension points:
eps.bar_shape = function getShape(){
var val = this.scene.vars.value.value;
if(val == 1.1 || val == 2.1 || val == 3.1){
return 'cross';
}
else {}
};
// Serialize back eps into cccOptions
cccOptions.extensionPoints = Dashboards.objectToPropertiesArray(eps);
}
How can we achieve this?
I hope the answer is still relevant, given that this is a late response.
To use bubbles you should have useShapes: true.
You can set a different constant shape by using the shape option. For example, shape: "cross".
To have the bubble size be constant, you should set the "sizeRole" to null: sizeRole: null. Bubbles will take all of the available "cell" size.
Then, the "value" column should be picked up by the "colorRole", but to be explicit, specify: colorRole: "value".
By default, because the color role will be bound to a continuous dimension ("value"), the color scale will be continuous as well.
To make it a discrete scale, change the "value" dimension to be discrete:
dimensions: {
"value": {isDiscrete: true}
}
Finally, to ensure that the colors are mapped to the desired values, specify the "colorMap" option:
colorMap: {
"1": "green",
"2": "yellow",
"3": "red"
}
That's it. I hope this just works :-)
Related
Well, I want to color my scatter using a vector with values. Actually, I want to use other dimension than the one used for creating the scatter.
Using these lines it gives a color to my scatter using the values given by the dimension that scatter is built on.
.colorAccessor(function(d) {return d.key[1]})
.colors(d3.scaleSequential(d3.interpolateOranges))
.colorDomain(y_range)
y_range = [y_min, y_max]
I tried to include the column for color in the dimension of the scatter, but it slows down the process of filtering. Something like this:
scatterDim = crossFilter.dimension(function(d) { return [d[it.variable[0]], d[it.variable[1]], d[it.color]]})
.colorAccessor(function(d) {return d.key[2]})
.colors(d3.scaleSequential(d3.interpolatePlasma))
.colorDomain([colorUnits[0], colorUnits[colorUnits.length - 1]]),
I want to have a different dimension for color:
colorDimension = crossFilter.dimension(function (d) { return d[it.color] }),
colorGroup = colorDimension.group().reduceCount(),
colorAll = colorGroup.all(),
colorUnits = [],
count = 0;
for(var color in colorAll)
{
colorUnits[count] = colorAll[color].key;
count++;
}
.colorAccessor(//some different code for my vector colorUnits or even for dimension?!//)
.colors(d3.scaleSequential(d3.interpolatePlasma))
.colorDomain([colorUnits[0], colorUnits[colorUnits.length - 1]]),
I would also like to know how to use scaleOrdinal for color. In case that the vector colorUnits contains strings.
The name "dimension" is a little confusing in crossfilter and dc.js. It isn't used to describe the "Y" (aggregated) values, or the color.
It really means, "I want to bin my data by this key, and filter on it."
The reason you will find color as a third element in dimension keys in many examples is that it's expedient. It's easier to change the keys than the aggregated values. But it doesn't really make sense.
The fact that your chart got slower when you added color to your dimension key tells me that you don't have a unique color for each X/Y pair. Instead of drawing a dot for each X/Y pair, you end up with a dot for each X/Y/color triplet.
You also don't need to create a separate color dimension unless you want to bin, aggregate, or filter on color.
Assuming you only want one dot per X/Y pair, you need to decide which color to use. Then you can change the reduction, instead of the key, to add this data:
scatterDim = crossFilter.dimension(function(d) {
return [d[it.variable[0]], d[it.variable[1]]];
}),
scatterGroup = scatterDim.group().reduce(
function(p, v) { // add
p.count++; // reduceCount equivalent
p.color = combine_colors(p.color, v[it.color]);
return p;
},
function(p, v) { // remove
p.count--;
// maybe adjust p.color
return p;
},
function() { // init
return {count: 0, color: null};
}
);
If you don't care which of the colors is used, you don't need combine_colors; just use v[it.color]. Otherwise, that's something you need to decide based on your application.
Now the scatter group has objects as its values, and you can change the scatter plot to take advantage of them:
scatterPlot
.existenceAccessor(d => d.value.count) // don't draw dot when it is zero
.colorAccessor(d => d.value.color)
If in fact you do want to draw all the dots with different colors, for example using opacity to allow overplotting, you probably need a canvas implementation of a scatter plot, because SVG is only good up to thousands of points. There is one in the works for dc.js but it needs to be ported to the latest APIs.
I would also like to know how to use scaleOrdinal for color. In case that the vector colorUnits contains strings.
Not sure what you mean here. scaleOrdinal takes strings as its domain, so
.colors(d3.scaleOrdinal(colorUnits, output_colors))
should work?
Example
Since I'm failing to communicate something or another, here is an example. The color strings come from an array since I don't have an example of your data or code:
const names = ["Zero", "One", "Two", "Three", "Four", "Five"];
speedSumGroup = runDimension.group()
.reduce(
function(p, v) { // add
p.count++; // reduceCount equivalent
p.color = names[+v.Expt];
return p;
},
// ... as before
);
chart
.colorAccessor(d => d.value.color)
.colors(d3.scaleOrdinal(names, d3.schemeCategory10))
Once again, if the method isn't working for you, the best way to figure it out is to log speedSumGroup.all(). I get:
[
{
"key": [
1,
850
],
"value": {
"count": 1,
"color": "One"
}
},
{
"key": [
1,
880
],
"value": {
"count": 1,
"color": "Three"
}
},
{
"key": [
1,
890
],
"value": {
"count": 2,
"color": "Five"
}
},
// ...
]
Example fiddle.
I have my class defined in "unscaled.BL_yFYield_CSUSHPINSA" (basically, 1:up 0:down). I wish to color the scatterplot into classes akin to how this example demonstrates species are supposedly highlighted by 3 colors (note, I've reduced my example to two colors).
http://www.sthda.com/english/wiki/scatter-plot-matrices-r-base-graphs
this image specifically is what I'm trying to achieve (coloring based on my_cols and a categorical variable). In the iris example, I only saw two species (when I iterated iris$species), but the online code uses 3 colors in the graph, so I'm not sure how that works data.
My example I have two colors for two classes (however, eventually I wish to extend my number of classes beyond 2).
Example, assuming BL_yFYield_CSUSHPINSA had the following values for categorical 0, 1, 2 and I had 3 colors defined in my_cols.
Right now when I graph the output, this is what I get
pre_MyData <- read.csv(file="https://raw.githubusercontent.com/thistleknot/FredAPIR/master/reduced.csv", header=TRUE, sep=",")
MyData <- pre_MyData[,11:18]
my_cols <- c("#00AFBB", "#E7B800")
pairs(MyData[,1:8], pch = 19, cex = 0.5,
col = my_cols[MyData$unscaled.BL_yFYield_CSUSHPINSA],
lower.panel = NULL)
I thought about it. The answer was in my screenshot. my_cols is skipping values with 0 in BL_yfield... (treating it as null). I could try to fix it after the fax, or I could add 1 to my original dataset to remove 0's...
problem solved
pre_MyData <- read.csv(file="https://raw.githubusercontent.com/thistleknot/FredAPIR/master/reduced.csv", header=TRUE, sep=",")
MyData <- pre_MyData[,11:18]
my_cols <- c("#00AFBB", "#E7B800")
pairs(MyData[,1:8], pch = 19, cex = 0.5,
col = my_cols[MyData$unscaled.BL_yFYield_CSUSHPINSA+1],
lower.panel = NULL)
I have got this silly problem.
I am creating a simple serial chart, displaying columns for two simple data series. The values are quite clse to eachother so amCharts decides to hide the 0 value axis and dislay only the relevant data. This is all good, but the thing is that I need to be able compare my columns visually. I also want to hide the labels on the value axis at some point.
Generally what I get now is this:
As you can see, value axis starts counting from 22.5. I need it to always start counting from 0, so I can compare the columns relatively to each other in a visual way. I know I can set the minimum propert of the value axis to 0 to achieve my desired result. But when I set any of the values to be negative, it does not display on the chart.
This is what I get with the minimum property set to 0 and one of the data points set o a negative value:
Here is a demo of my problem:
http://jsfiddle.net/gregzx/scyhwws4/1/
minimum set to 0 and one of the values set to a negative value.
Summing up: I need to always display the 0 value on the value axis AND be able to display negative values. Any hints will be much appreciated!
You could use a negative value for the minimum setting as well. As an example, you could set your minimum value to -30 and the maximum setting to 30.
This also makes sure that the 0-line is in the vertical middle.
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
// ...
"valueAxes": [{
"minimum": -30,
"maximum": 30
}],
// ...
});
I had this problem at work and just solved it perfectly, You need to determine if there are any negative values in the incoming chart data, and of course, you want to avoid all negative values, so you also need a Boolean value to determine if the values are all negative.
Here's how I did it:
// your chart component
const XXXChart = ({ chartData }) => {
const hasNegative = chartData.some((it) => it.value < 0)
const allNegative = chartData.every((it) => it.value < 0)
useLayoutEffect(() => {
...
valueAxis.min = 0 // set with zero, assume that chartData defaults to positive values
if(hasNegative){
valueAxis.min = undefined // when there are negative and positive values, valueAxis.min will be restored to undefined, because valueAxis.max is undefined by default, and then chart will automatically set zero line.
valueAxis.max = allNegative ? 0 : undefined // When all values are negative, valueAxis.max can be set directly to zero
}
...
}, [chartData])
}
This is the perfect solution to your current problem.
Based on this example:
https://cdn.rawgit.com/hkelly93/d3-relationshipGraph/master/examples/index.html
D3 should allow me to create this chart and define colors and thresholds for when values change color. The function accepts some custom settings:
var graph = d3.select('#graph').relationshipGraph({
maxChildCount: 10,
valueKeyName: 'Story title',
thresholds: [6, 8, 10],
colors: ['red', 'yellow', 'green'],
showTooltips: true
})
But I'm not getting a graph with three colors when I load data fitting into all 3 ranges. I want 0-6 to appear red, 7-8 to appear yellow, and 9-10 to appear green. Here's the data loaded (excerpt):
[
{"parent": "2012-October", "organization": "WEWASAFO", "value": 10, "Story title": "NUTRITION"},
{"parent": "2012-April", "organization": "Jitegemee", "value": 5, "Story title": "Life in the street"},
{"parent": "2011-May", "organization": "KENYA YOUTH BUSINESS TRUST (KYBT)", "value": 2, "Story title": "BUSINESS"}
]
Everything else parses correctly, except combining custom colors an custom thresholds on the same chart. Either one alone works, but not both together.
The source repo is here with some docs:
https://github.com/hkelly93/d3-relationshipgraph
From that documentation:
thresholds: [100, 200, 300], // The thresholds for the color changes. If the values are strings, the colors are determined by the value of the child being equal to the threshold. If the thresholds are numbers, the color is determined by the value being less than the threshold.
colors: ['red', 'green', 'blue'], // The custom color set to use for the child blocks. These can be color names, HEX values, or RGBA values.
It doesn't explicitly state that the child colors correspond to the order that the thresholds appear. And all blocks appear red in this example.
I tested the code here: https://jsfiddle.net/cgrx3e9m/
This turned out to be a bug in the module itself. I notified the author and he fixed the way it sorts thresholds so it matches up with corresponding colors now.
I'm working on a visualization tool for time series with multiple dimensions.
To simplify my case, each data-point has a dimension on type, clusterId and a set of months:
{
type: "green",
clusterId:42,
months:[1392185580000, 1394604780000, 1397279580000]
}, {
type: "red",
clusterId:43,
months:[1392185580000]
}
Now I would like to show the dates in a dc.barChart, which shows the months of all datasets as keys(bars), and the number of observations of each month as value of the bar.
In the given case, it would result in 3 bars, the first one with a height of 2, and the other with a height of 1.
How can I create this dimension and implement the grouping/reducing function?
You don't have to worry about filtering by this dimension, I already have a custom filter for this dimension. The only thing is displaying the bars on the barChart.
If i get this correctly, you need some code, that outputs: 1392185580000: 2, 1394604780000: 1, 1397279580000:1?
arr.forEach(function(d) {
d.months.forEach(function(month) {
if (!store.hasOwnProperty(month)) {
store[month]=0;
}
store[month]++;
});
});
demo fiddle