Google Chart Data Grouping - google-visualization

I want a feature for my Google Chart. Such that, if the number of series is greater than a specified number, the remaining series will be grouped together into one series.
For example, I have 5 series of fruits: Apple, Banana, Orange, Mango, Avocado
And my series limit is 3.
My graph will show: Apple, Banana, Orange, Others.
What happened is that the remaining series (Mango and Avocado) were grouped together into 'Others'.
Does Google Charts have a feature for this (e.g: aggregators probably) ?

Use a DataView to combine your extra columns into one:
// assumes you have a DataTable "data" with 6 columns (one domain, plus your 5 fruits)
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, 2, 3, {
type: 'number',
label: 'Others',
calc: function (dt, row) {
// combine columns 4 and 5 together:
return dt.getValue(row, 4) + dt.getValue(row, 5);
}
}]);

Related

Power Bi nested list in string

So i have the following problem:
I'm trying to import some data from my database into my report.
The data is provided by some views, which already have predetermined datatypes for my columns.
Although they are not all correct. And here lies the problem.
An example would be:
items (type = int)
itemDetails (type = string)
1
[[[Fruit], Fruit, Apple, 0.90]]
2
[[[Fruit], Fruit, Apple, 0.90],[[Veggie], Veggie, Salat, 1.50]]
Now the problem is, that Power Bi doesn't recognize the data in the second column as a list, or an array.
My goal is to extract the informations in these nested lists: so the desired output would be something like:
items (type = int)
itemDetails
itemCategory
itemName
itemPrice
1
[[[Fruit], Fruit, Apple, 0.90]]
Fruit
Apple
0.9
2
[[[Fruit], Fruit, Apple, 0.90],[[Veggie], Veggie, Salat, 1.50]]
Fruit, Veggie
Apple, Salat
0.9, 1.5

PowerBI Custom Visual - Table data binding

Also asked this on the PowerBI forum.
I am trying to change sampleBarChart PowerBI visual to use a "table" data binding instead of current "categorical". First goal is to build a simple table visual, with inputs "X", "Y" and "Value".
Both data bindings are described on the official wiki. This is all I could find:
I cannot find any example visuals which use it and are based on the new API.
From the image above, a table object has "rows", "columns", "totals" and "identities". So it looks like rows and columns are my x/y indexes, and totals are my values?
This is what I tried. (Naming is slightly off as most of it came from existing barchart code)
Data roles:
{ "displayName": "Category1 Data",
"name": "category1",
"kind": 0},
{ "displayName": "Category2 Data",
"name": "category2",
"kind": 0},
{ "displayName": "Measure Data",
"name": "measure",
"kind": 1}
Data view mapping:
"table": {
"rows": {"for": {"in": "category1"}},
"columns": {"for": {"in": "category2"}},
"totals": {"select": [{"bind": {"to": "measure"}}]}
}
Data Point class:
interface BarChartDataPoint {
value: number;
category1: number;
category2: number;
color: string;
};
Relevant parts of my visualTransform():
...
let category1 = categorical.rows;
let category2 = categorical.columns;
let dataValue = categorical.totals;
...
for (let i = 1, len = category1.length; i <= len; i++) {
for (let j = 1, jlen = category2.length; j <= jlen; j++) {
{
barChartDataPoints.push({
category1: i,
category2: j,
value: dataValue[i,j],
color: "#555555"//for now
});
}
...
Test data looks like this:
__1_2_3_
1|4 4 3
2|4 5 5
3|3 6 7 (total = 41)
The code above fills barChartDataPoints with just six data points:
(1; 1; 41),
(1; 2; undefined),
(2; 1; 41),
(2; 2; undefined),
(3; 1; 41),
(3; 2; undefined).
Accessing zero indeces results in nulls.
Q: Is totals not the right measure to access value at (x;y)? What am I doing wrong?
Any help or direction is very appreciated.
User #RichardL shared this link on the PowerBI forum. Which helped quite a lot.
"Totals" is not the right measure to access value at (x;y).
It turns out Columns contain column names, and Rows contain value arrays which correspond to those columns.
From the link above, this is how table structure looks like:
{
"columns":[
{"displayName": "Year"},
{"displayName": "Country"},
{"displayName": "Cost"}
],
"rows":[
[2014, "Japan", 25],
[2015, "Japan", 30],
[2016, "Japan", 18],
[2015, "North America", 14],
[2016, "North America", 30],
[2016, "China", 100]
]
}
You can also view the data as your visual receives it by placing this
window.alert(JSON.stringify(options.dataViews))
In your update() method. Or write it in html contents of your visual.
This was very helpful but it shows up a few fundamental problems with the data management of PowerBI for a custom visual. There is no documentation and the process from Roles to mapping to visualTransform is horrendous because it takes so much effort to rebuild the data into a format that is usable consistently with D3.
Commenting on user5226582's example, for me, columns is presented in a form where I have to look up the Roles property to be able to understand the order of data presented in the rows column array. displayName offers no certainty. For exampe, if a user uses the same field in two different dataRoles then it all gets crazily awry.
I think the safest approach is to build a new array inside visualTransform using the known well-field names (the "name" property in dataRoles), then iterate columns interrogating the Roles property to establish an index to the rows array items. Then use that index to populate the new array reliably. D3 then gobbles that up.
I know that's crazy, but at least it means reasonably consistent data and allows for the user selecting the same data field more than once or choosing count instead of column value.
All in all, I think this area needs a lot of attention before custom Visuals can really take off.

Python 2: How do I pull a value from a matrix of options based on multiple test values?

Let's say I have two colors of blocks, red and blue. Let's also say that blocks have a number on them (regardless of color, and numbers can be repeated). So we could have the following blocks:
block_one = {"color": "red", "value": 1}
block_two = {"color": "red", "value": 3}
block_three = {"color": "blue", "value": 1}
I have the following table of prices:
Red Blue
1 10 15
2 20 17
3 30 19
What is an efficient way for me to figure out the price based on the two pieces of data I have for each block?
Example: What is the price of block_one, and I want an output of 10.
I've been writing nests of if-elif testing multiple dictionaries of prices, but it is 1.) convoluted and ugly and 2.) slow.

Google Chart Customization

I want following Google Chart (Column Chart) to show its first label on horizontal axis. Also I want each column to have same width; first and last column need a change. How is it possible?
var chartDataRaw = [{
"month": "201211",
"articles": 41467
}, {
"month": "201212",
"articles": 31820
}, {
"month": "201301",
"articles": 43817
}, {
"month": "201302",
"articles": 42773
}, {
"month": "201303",
"articles": 38695
}, {
"month": "201304",
"articles": 41257
}];
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('date', 'Month');
dataTable.addColumn('number', 'Articles');
var i = 1;
//chartDataRaw is array of objects, requested from server. looped through jquery each to fill dataTable
$.each(chartDataRaw, function () {
var year = this.month.substring(0, 4);
var month = this.month.substring(4);
var dataItem = [new Date(year, month), this.articles];
dataTable.addRow(dataItem);
});
var options = {
title: 'Company Coverage',
hAxis: {
title: 'Last Six Months',
titleTextStyle: {
color: 'red'
},
format: 'MMM, yyyy',
fontSize: '8px'
},
vAxis: {
textPosition: 'none'
},
trendlines: {
0: {
color: 'black',
lineWidth: 3,
opacity: 0.4
}
},
legend: 'none'
};
var monthYearFormatter = new google.visualization.DateFormat({
pattern: "MMM, yyyy"
});
monthYearFormatter.format(dataTable, 0); //change date format to render on chart
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(dataTable, options);
http://jsfiddle.net/YyYsN/2/
Edit: Added chart data
Executive Summary
You are committing several mortal sins:
You are not defining dates right
You have no y axis values distorting your data
You are using columns to describe a continuous series
You are predicting based on only 6 data points
You are not defining dates right
Look at the value for January 2013. It says 31,820 articles. The issue is your data says there were 43,817 articles in January. What the heck is going on?
Javascript Date Objects use month values from 0-11, not 1-12. That means when you convert the dates, you need to change your function.
Old:
var dataItem = [new Date(year, month), this.articles];
New:
var dataItem = [new Date(year, month - 1), this.articles];
You have no y axis values distorting your data
Compare the second bar to the third bar. What is the ratio between the two? It looks like the second bar is around .5 gridlines, and the third bar is around 3.5 gridlines. That is a 700% increase in articles!
Only if you look at the data, it's actually going from 31,820 to 43,817, and increase of only 37%.
Bar charts should always start from zero, otherwise you get incredibly distorted perspective of the data, especially when there are no labels to boot.
Old:
vAxis: {
textPosition: 'none',
},
New:
vAxis: {
textPosition: 'none',
minValue: 0
},
You are using columns to describe a continuous series
Columns show discrete items. If I want to poll how many kids in a class like dogs, cats, and iguanas, a column chart is great since it allows me to compare the popularity (height) across unrelated categories (horizontal). Columns are okay for showing sales per month (or articles per month), but by making them columns you are implying that the columns should be compared as individual items, not as a progressing series.
If you want to show that these data items are connected (as implied by the trendline) it would make much more sense to show an area chart.
(Ideally, the area chart would show articles over the last 30 days, and have daily data, rather than a monthly compilation since months are arbitrary cutoffs, and things like weekends and holidays probably have a significant impact on your data which further distorts what you're trying to show).
Old
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
New
var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
You are predicting based on only 6 data point
Six points does not a trend make. Your data's highest value is the second point, yet you are showing the trend increasing over time. Perhaps the trendline suggests an upward trend (since the later values are higher than the first value), but as soon as you move 1 month forward you will have a descending trendline (barring a massive increase in articles).
This makes no rational sense. 5 months of data are the same. How can changing 1 month of a 6-month series change the direction of the trendline? Forecasting is iffy-enough as it is (see the Black Swan theory), but doing it on a minimal 6-month series likely isn't the best. This means the trendline should probably be removed altogether since it not only doesn't convey useful information, it potentially conveys incorrect information.
Summary
That said, if you just want your left and right columns not to be cut off, you can change the following code:
Old
hAxis: {
title: 'Last Six Months',
titleTextStyle: {
color: 'red'
},
format: 'MMM, yyyy',
fontSize: '8px',
},
New
hAxis: {
title: 'Last Six Months',
titleTextStyle: {
color: 'red'
},
format: 'MMM, yyyy',
fontSize: '8px',
minValue: new Date(2012,9),
maxValue: new Date(2013,4)
},
fixed it myself by changing corechart visualization version to 1.1
google.load("visualization", "1.1", {packages:["corechart"]});

put labels on top of inside bar in google interactive bar chart

I have created a bar chart using google Column Chart, now
I have only integer values in my datatable but google divide acis with float values, is there a way to force chart mark only integers?
is there any way to show value labels on top or inside bar chart? I found some way for image chart, but I whould like to keep chart interactive
There is no direct solution to this as yet because annotations are not supported in column chart. But let me share a work around for this: You can create a combo chart with two series having same data (as that of your column chart) along with the annotation column. Set the type of the first series to bars and that of the other series to line. Finally, specify visibleInLegend, lineWidth, and pointSize properties of the second series to false and 0s respectively.
var data = new google.visualization.DataTable();
data.addColumn({ type: 'string', label: 'Labels' });
data.addColumn({ type: 'number', label: 'Bar Series' });
data.addColumn({ type: 'number', label: 'Line Series' });
data.addColumn({ type: 'string', role: 'annotation' });
data.addRows([['Label1', 10, 10, '10'],
['Label1', 20, 20, '20'],
['Label1', 40, 40, '40'],
['Label1', 5, 5, '5'],
['Label1', 30, 30, '30'],
]);
var barchart = new google.visualization.ComboChart(document.getElementById('bar_element'));
var options = {series: [{ type: 'bars' },
{ type: 'line', lineWidth: 0, visibleInLegend:false, pointSize: 0}]};
barchart.draw(data, options);
For your first problem you can use gridlines property, take a look at this post to see how you can use it.
For the second question I don't really understand. When you go on a bar with your mouse, the popup with values isn't already displayed on the top of the bar?