Can Google Charts support dual y-axis (v-axis)? - charts

The Flot chart api supports dual v-axis scales, as shown by this example.
I'm using Google Charts - is this possible also with Google? I've had a look through the examples and docs, but can't find any examples / references to indicate it does support dual axis charts.

It took me a while, to figure this out, but Google Charts does support dual Y-axis (v-axis). I want to use the Javascript API and not the HTML interface.
This example can be tested here:
http://code.google.com/apis/ajax/playground/?type=visualization#line_chart
Replace all of that code with this code showing how to have two different Y-axis scales:
function drawVisualization() {
// Create and populate the data table.
var data = new google.visualization.DataTable();
data.addColumn('string', 'x');
data.addColumn('number', 'Cats');
data.addColumn('number', 'Blanket 1');
data.addColumn('number', 'Blanket 2');
data.addRow(["A", 1, 1, 0.5]);
data.addRow(["B", 2, 0.5, 1]);
data.addRow(["C", 4, 1, 0.5]);
data.addRow(["D", 8, 0.5, 1]);
data.addRow(["E", 7, 1, 0.5]);
data.addRow(["F", 7, 0.5, 1]);
data.addRow(["G", 8, 1, 0.5]);
data.addRow(["H", 4, 0.5, 1]);
data.addRow(["I", 2, 1, 0.5]);
data.addRow(["J", 3.5, 0.5, 1]);
data.addRow(["K", 3, 1, 0.5]);
data.addRow(["L", 3.5, 0.5, 1]);
data.addRow(["M", 1, 1, 0.5]);
data.addRow(["N", 1, 0.5, 1]);
// Create and draw the visualization.
new google.visualization.LineChart(document.getElementById('visualization')).
draw(data, {curveType: "function", width: 500, height: 400,
vAxes: {0: {logScale: false},
1: {logScale: false, maxValue: 2}},
series:{
0:{targetAxisIndex:0},
1:{targetAxisIndex:1},
2:{targetAxisIndex:1}}}
);
}
By adding maxValue: 2 to the code, and setting series 1 & 2 to that axis, they work properly on a second axis.

Non-JavaScript solution
Assuming that you are looking for a series that shares that same X-axis (horizontal) but has different values (and scales) for the Y-axis (vertical) then you can do this without recourse to JavaScript as follows:
Select Insert | Chart from the menu.
Double-click the chart, and in the chart editor select Chart Type | Line chart.
Click the grid icon in the "Data range" box to get the data range dialog.
Click the worksheet containing the data you're interested in for the Y-axis lines and highlight from the top left to the bottom right so you cover all the Y-axis lines. You can tidy up the columns later.
Click OK and you'll see a collection of series has been extracted. Use the "dot menu" for each series to remove those you're not interested in.
Click the grid icon in the "X-axis" box to the get the data range dialog once again.
Click the worksheet containing the data you're interested in for the X-axis line and highlight from the top to the bottom.
Click OK and you'll see the X-axis has been filled in and both Y-axis lines are sharing the same left axis label.
Click on the line you want to use the right axis label for and use the "Axis" box in the chart editor dialog to select "Right axis".
You can now edit the various other properties of the chart to get it to look the way you want in terms of presentation.

I did it.
Click on the data series
A small box will appear with 2 small squares with only two bold sides each
Click on the second one
Might be done then.

Related

show multiple axis to highcharts chart and present axis to left

Trying to create a chart as show below
Tried to get most of it working fiddle is in
https://jsfiddle.net/BlackLabel/j1pz28y3/
But only axis is the issue. Unable to get multiple axis for different chart and also axis on the left rather than right please help me by pointing to some demo
You need to set yAxis.opposite to false. Your image shows only two axis (first one for the line and flag series, the second one for the column), so here is the example config basing on the image:
yAxis: [{
opposite: false,
height: '60%'
}, {
opposite: false,
top: '65%',
height: '40%',
offset: 0
}],
Demo:
https://jsfiddle.net/BlackLabel/at8Lyod4/
API Reference:
https://api.highcharts.com/highstock/yAxis.opposite

Altair: How to make scatter plot aligned with image background created by mark_image?

I'm looking for a working example to have a .png picture as the background of a scatter chart.
Currently, I use mark_image to draw the background image:
source = pd.DataFrame.from_records([
{"x": 0, "y": 0,
"img": "http://localhost:8888/files/BARTStreamlit/assets/BARTtracksmap.png?_xsrf=2%7Ce13c35be%7Ce013c83479b892363239e5b6a77d97dc%7C1652400559"}
])
tracksmap = alt.Chart(source).mark_image(
width=500,
height=500
).encode(
x='x',
y='y',
url='img'
)
tracksmap
Here is the resulted image drown:
and draw the scater chart,
chart = alt.Chart(maptable).mark_circle(size=60).encode(
x= 'x',
y= 'y',
tooltip=['short_name', 'ENTRY']
).interactive()
chart
I have scaled the x, y channel values for the scatter chart to be in the range of [0, 500]. 500 is the width and height of the background image that I guessed.
Here is the resulted scatter plot:
then I combined the two chart with layer mechanism:
geovizvega = alt.layer(tracksmap, chart)
geovizvega
resulting the following:
The two charts do not align. I'd like to have the scatter dots aligning with the tracks on the background image. How can I achieve that?
To have them aligned, I might need to have the background image's top left corner at the coordinates (0, 0), how can I achieve that? (It seems that the x, y channel values for mark_image is the coordinates of the center of the image? With accurate definition of the x, y channel values, it might be possible to calculate the proper value of x, and y for the top left coroner to be at (0, 0)).
I might need to to have precise dimension of the background image. How?
My above approach may not be the right one. Please show me a working example.
Yes, if you change the values of x and y in your image plot to something like y=-200 and x=200, the image should be more centered in the scatter plot.
You can also change the anchor point of the image using align and baseline:
import altair as alt
import pandas as pd
source = pd.DataFrame.from_records([
{"x": 2, "y": 2, "img": "https://vega.github.io/vega-datasets/data/7zip.png"}
])
imgs = alt.Chart(source).mark_image(
width=100,
height=100
).encode(
x='x',
y='y',
url='img'
)
imgs + imgs.mark_circle(size=200, color='red', opacity=1)
imgs = alt.Chart(source).mark_image(
width=100,
height=100,
align='right',
baseline='top'
).encode(
x='x',
y='y',
url='img'
)
imgs + imgs.mark_circle(size=200, color='red', opacity=1)
After this, you would still need to change the dimensions of the chart so that it has the same size as the image. The default is width=400 and height=300. You can get the dimensions of your image in most image editing software or using the file <imagename> command (at least on linux). But even after getting these dimensions, you would have to do some manual adjustments due to axes taking up some of that space in the chart.

Highcharts - navigation by 3rd element in series 'hidden' in plot

I have some info which is in this format (speed, frequency, date). What happens is that I need to plot this chart with speed x frequency, but I want to allow the users to use the navigation filtering by the date, which is not appearing on the chart.
Also, I have some info which is not built dynamically, which is the limits of speed x frequency. This info will be fixed as reference points on the plot. So, when I filter the plot info (not the limits), it must always display these limit plots.
You can have an idea by this chart, the area plots show the limits for the points (speed, frequency). Then, I would add points of speed x frequency (x date), and filter then by date.
Can you guys give me some advice on this?
here is a JSFIDDLE
JSFIDDLE
data: [
[0, 20, here is a date], [10, 20,here is a date],
[50, 39.9994, here is a date], [100,49.7494, here is a date]
],
Guys, notice that every element of the array in the series has 3 elements [a, b, c], suppose the third one (c) is a DATE and not a random number as it is right now. I want to be able to use the commented the navigator code to filter this series by this C element, which doesn't in fact appear on the chart you see, it is a hidden element, just to filter the data.
There will be a little tricky, if you want to have a navigator in the same chart. Navigator works only with datetime data and it must be connected with the axis from the main chart.
So, you have data in that format:
var points = [
[5, 9, Date.UTC(2016, 1, 0)],
[65, 6, Date.UTC(2016, 1, 1)],
...
You need two x axes - one which represents the data and the other which is connected to the navigator. The second axis must be visible to work with the navigator and must be connected with the datetime data.
So now, except two x axes, you need two series - one with the actual data, and the other consists of [date, y] values from the first series. The additional data will be visible in the navigator - note, that in the navigator you cannot use scatter series - so it will be converted to line series - to happen it without errors, your data should be sorted by date.
series: [{
id: 'main-series',
data: points.map(function(point) {
return [point[0], point[1], point[2], point[1]]
}),
showInNavigator: false,
xAxis: 1,
keys: ['x', 'y', 'date', 'holdY'] //holdY is for easier hiding points
}, {
xAxis: 0,
data: points.map(function(point) {
return [point[2], point[1]];
}),
showInNavigator: true,
enableMouseTracking: false,
color: 'transparent',
showInLegend: false
}],
xAxis: [{
minRange: 1000 * 3600 * 24,
type: 'datetime',
tickLength: 0,
tickLength: 0,
labels: {
enabled: false
},
}, {
type: 'linear'
}],
The last thing you need a callback which will hide/show points after the extremes in the navigator are set. Hiding/showing depends on the third point's property which is date. There is no directly API to hide/show specific points (except pie), but it can be achieved by setting point's value to null (that is why I preserved the real y in holdY).
events: {
afterSetExtremes: function(e) {
var points = this.chart.get('main-series').points;
points.forEach(function(point) {
point.update({
y: e.min <= point.date && point.date <= e.max ? point.holdY : null
}, false, false);
});
this.chart.redraw();
}
}
example: https://jsfiddle.net/3wuwdonn/1/
I would consider using a navigator as a separate chart, then you wouldn't need the second x axis and series in the main chart and you wouldn't need to make them look invisible.
example with a navigator only chart here: http://jsfiddle.net/f7Y9p/

How to change radial tick markers in Matlab polar plot?

I'd like to relabel the radial tick markers in the following polar log plot:
f = figure ;
t = 0:0.01: pi/2 ;
polar(t, 10 * log10(cos(t))/(50) + 1)
from 1, 0.8, 0.6, 0.4, 0.2 to 0, -10, -20, -30, -40 (i.e. radial dB ticks).
Trying some of the methods from Fixing the Radial Axis on MATLAB Polar Plots, I was able to relabel the markers provided my tick markers were positive and increasing.
I tried the following based on How to remove Rho labels from Matlab polar plot?
rho_labels = {'1' '0.8' '0.6' '0.4' '0.2'};
rho_labels2 = {'0' '-10' '-20' '-30' '-40'};
for r=1:length(rho_labels)
ff = findall(f, 'string', rho_labels{r}) ;
ff = rho_labels2{r} ;
end
but it also didn't work (seems to do nothing, so I suspect I'm operating on a copy of the find results not handled).
How can these tick markers be adjusted? Also, if I wanted a different number of concentric circles than 5, how can that be done (for example, 4 subdivisions with -40 dB at the "origin".)
Here is a way to rename the radial tick labels. Be warned that if there is a match between any radial and angular tick mark labels, both will be replaced and the angular labels will be wrong. But the angular tick labels are fixed as 0, 30, 60, ..., 330, so as long as the radial tick labels don't include these values, you should be fine.
What the code does is find all the text in the plot using findall, trim the blank spaces at the front of each string, then, for each entry in rho_labels, set the string entry corresponding to the tick label with that identifier to the corresponding entry in rho_labels2.
f = figure ;
t = 0:0.01: pi/2 ;
polar(t, 10 * log10(cos(t))/(50) + 1)
rho_labels = {'1' '0.8' '0.6' '0.4' '0.2'};
rho_labels2 = {'0' '-10' '-20' '-30' '-40'};
ff = findall(f,'type','text');
t=strtrim(get(ff,'String'));
for r=1:length(rho_labels)
set(ff(strcmp(t,rho_labels{r})),'String',rho_labels2{r})
end
To modify the number of rings, I think think of anything better than modifying polar.m and creating your own custom polarMOD.m function. If you do this you can also do the radial labels as well. In fact, there might be such a function on the MathWorks File Exchange.

Google Scatter Charts, Different Point Size

I am using Google Scatter Chart APIs to try to plot a punch card chart like the one Github has. I don't know how to change the marker size of each point shown. Is it possible in this API?
Yes, this is possible, though not if using the new Material Design scatter plot (created with new google.charts.Scatter()). If using the normal Scatter Plot though (created with new google.visualization.ScatterChart()), you do this by passing a style parameter for each point along with your data.
So for instance, if each point is usually defined [x, y], instead you would define it as [x, y, point_style].
An example of point_style would be 'point { size: 12; shape-type: circle; fill-color: #FFFFFF; color: #CCCCCC }';
Thus a sample data point would be [10, 5, 'point { size: 12; shape-type: circle; fill-color: #FFFFFF; color: #CCCCCC }']
Finally, you need to make sure you've added a style column to your set of data columns, like so:
var data = new google.visualization.DataTable();
data.addColumn('number', x_axis_title);
data.addColumn('number', y_axis_title);
data.addColumn( {'type': 'string', 'role': 'style'} ); // Defines point style
If you've done these things --- added a style data column and defined a style for each individual point --- then your custom styles will appear on the chart.
You can also define a pointSize and pointShape in the graph's options if you want to set them for all points at once, but you can't define individual points that way, so the above method is better if you want more granular control.