R plot_ly row or dataframe in PowerBI custom visuals - r

I am following: http://radacad.com/create-custom-visual-with-r-and-json-part3
Here it is mentioned that with below R code, we can plot the chart:
Values<-data.frame(X,Y,Legend,Row,Column)
g=ggplot(Values, aes(x=X, y=Y,colour = Legend))
I am using similar implementations.
Below code renders blank chart with only axis:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = ~mpg_test,
y = ~cyl_test,
name = "SF Zoo",
type = "bar"
)
Empty chart
Below code also renders empty chart:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = mpg_test,
y = cyl_test,
name = "SF Zoo",
type = "bar"
)
Below code renders correct chart:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = ~mpg_test[1:nrow(Values), ],
y = ~cyl_test[1:nrow(Values), ],
name = "SF Zoo",
type = "bar"
)
Correct chart:
My doubt is, as per the tutorial I must get columns in mpg_test and cyl_test, then why I am getting something like dataframe in here.
Does, plotly handles things differently with the usage of ~ ?
Please help. Also, is there any way I can use the mpg_test and cyl_test without nrow(Values) inside plot_ly
script.r
source('./r_files/flatten_HTML.r')
############### Library Declarations ###############
libraryRequireInstall("ggplot2");
libraryRequireInstall("plotly")
####################################################
################### Actual code ####################
Values <- data.frame(mpt_test, cyl_test)
p <- plot_ly(Values,
x = ~mpt_test[1:nrow(Values), ],
y = ~cyl_test[1:nrow(Values), ],
name = "SF Zoo",
type = "bar"
)
####################################################
############# Create and save widget ###############
#p = ggplotly(p);
internalSaveWidget(p, 'out.html');
####################################################
capabilities.json
{
"dataRoles": [
{
"displayName": "Mileage Per Gallon",
"kind": "GroupingOrMeasure",
"name": "mpg_test"
},
{
"displayName": "Cylinder Size",
"kind": "GroupingOrMeasure",
"name": "cyl_test"
}
],
"dataViewMappings": [
{ "conditions": [
{
"mpg_test": {
"max": 1
},
"cyl_test": {
"max": 1
}
}
],
"scriptResult": {
"dataInput": {
"table": {
"rows": {
"select": [
{
"for": {
"in": "mpg_test"
}
},
{
"for": {
"in": "cyl_test"
}
}
],
"dataReductionAlgorithm": {
"top": {}
}
}
}
},
"script": {
"scriptProviderDefault": "R",
"scriptOutputType": "html",
"source": {
"objectName": "rcv_script",
"propertyName": "source"
},
"provider": {
"objectName": "rcv_script",
"propertyName": "provider"
}
}
}
}
],
"objects": {
"rcv_script": {
"properties": {
"provider": {
"type": {
"text": true
}
},
"source": {
"type": {
"scripting": {
"source": true
}
}
}
}
}
},
"suppressDefaultTitle": true
}

Related

Returning a single element from an array with a join in azure Cosmos SQL DB

I have a query:
SELECT c.mainColour,t AS colour
FROM c
JOIN t IN c.creatorStyleMainColours
WHERE c.creatorDefaultStyleProfile = "test"
and it returns whole of the array inside the new colour object:
[
{
"colour": {
"mainColour": "black",
"colourPairings": [
"orange",
"silver",
"gold"
]
}
}
]
I need it to just return the main colour values
how do I just select the value of the "mainColour" so its a simple array like ["black","beige","white"] from the document below
I have tried:
SELECT VALUE c.mainColour,t AS colour
FROM c
JOIN t IN c.creatorStyleMainColours
WHERE c.creatorDefaultStyleProfile = "test"
but that returns a syntax error.
Here is the full document:
{
"accountId": "59951c4d-1f0b-483b-a020",
"creatorDefaultStyleProfile": "test",
"creatorDefaultStyleGender": "Female",
"creatorStyleAccountName": "",
"creatorStyleCategory": [
{
"categoryCode": "fashion",
"categoryName": "Fashion",
"categoryMetadata": {
"occasions": [
{
"occasionCode": "casual",
"occasionName": "Casual",
"occasionTypes": [
{
"occasionCode": "out",
"occasionName": "Everyday Wear"
}
]
}
],
"season": [
{
"seasonCode": "spring",
"seasonName": "Spring"
}
]
},
"id": "fashion"
}
],
"creatorStyleDescription": "",
"creatorStyleId": "Classic_Default",
"creatorStyleImages": [
{
"styleImageUrl": "https://4965fa50-6caf-11ed-8082e.png",
"styleImageCategory": "fullsize",
"styleImageResolution": {
"width": 269.25,
"height": 359
},
"styleImagePins": [
{
"itemId": "F243906F37487C78D7EB99880142B370",
"vector": {
"x": 198.125,
"y": 44.33332824707031
}
},
{
"itemId": "9B543E0DC1B05F6E9AFD0A88285AEEF9",
"vector": {
"x": 52.791656494140625,
"y": 46.33332824707031
}
},
{
"itemId": "3E6464FC1F12E3C6E435F751438F1468",
"vector": {
"x": 120.45832824707031,
"y": 320.3333282470703
}
},
{
"itemId": "1CD6065A4C7A0BD66E44DC8A62448534",
"vector": {
"x": 115.45832824707031,
"y": 192
}
}
]
}
],
"creatorStyleItems": [
{
"creatorStyleItemId": "9B543E0DC1B05F6E9AFD0A88285AEEF9",
"ItemType": "Chest",
"creatorStyleItemName": "t-shirt",
"creatorStyleItemImages": [
{
"imageUrl": "https://images/23660493-1-white?$XXL$",
"imageCategory": "thumbnail"
}
]
},
{
"creatorStyleItemId": "F243906F37487C78D7EB99880142B370",
"ItemType": "Chest",
"creatorStyleItemName": "chunky knit cardigan",
"creatorStyleItemImages": [
{
"imageUrl": "https://images/14399002-1-black?$XXL$",
"imageCategory": "thumbnail"
}
]
},
{
"creatorStyleItemId": "1CD6065A4C7A0BD66E44DC8A62448534",
"ItemType": "Leg",
"creatorStyleItemName": " mom jeans",
"creatorStyleItemImages": [
{
"imageUrl": "https://images-blue/202501450-1-denimblack?$XXL$",
"imageCategory": "thumbnail"
}
]
},
{
"creatorStyleItemId": "3E6464FC1F12E3C6E435F751438F1468",
"ItemType": "Feet",
"creatorStyleItemName": "trainers",
"creatorStyleItemImages": [
{
"imageUrl": "https://images./203112454-1-brown?$XXL$",
"imageCategory": "thumbnail"
}
]
}
],
"creatorStyleMainColours": [
{
"mainColour": "black",
"colourPairings": [
"beige",
"grey",
"white"
]
},
{
"mainColour": "beige",
"colourPairings": [
"black",
"grey",
"white"
]
},
{
"mainColour": "white",
"colourPairings": [
"beige",
"grey",
"black"
]
}
],
"creatorStyleMerchantGroup": "test1",
"creatorStyleName": "",
"creatorStyleProfiles": [
{
"id": "",
"profileAccountId": "test1",
"profileId": "test1",
"profileIsDefault": false,
"profileName": "classic",
"profileBiometric": {
"biometricName": "",
"biometricGender": "Female",
"biometricHeight": [
],
"biometricAgeRange": [
],
"biometricHairColour": [
],
"biometricSkinColour": [
],
"biometricBodyShape": [
],
"biometricMeasurement": {
}
},
"profilePersona": {
"personaName": "",
"personaDressSense": [
],
"personaInterests": [
],
"personaStyleIcons": [
],
"personaColours": [
]
}
}
],
"creatorStyleStatus": {
"styleStatusId": "nonpublished",
"styleStatusDescription": ""
},
"id": "classicStyle1",
"_rid": "IW43AJ08x+8BAAAAAAAAAA==",
"_self": "dbs/IW43AA==/colls/IW43AJ08x+8=/docs/IW43AJ08x+8BAAAAAAAAAA==/",
"_etag": "\"97005ae1-0000-1500-0000-638523be0000\"",
"_attachments": "attachments/",
"_ts": 1669669822
}

R: Nested data.table to JSON

I want to get from a data.table like this
temp <- data.table(data = list(data.table(a = 1:2,b=1:2)), type = "A")
data
type
<data.table[2x2]>
A
to a JSON like this
{
"group":
{
"data": [
{
"a": 1,
"b": 1
},
{
"a": 2,
"b": 2
}
],
"type": "A"
}
}
The Problem is I always end up with an additional array "[" for group.
What I have tried is tidyr::nest and
temp2 <- temp[, list(group=list(.SD))]
jsonlite::toJSON(temp2,pretty = TRUE, auto_unbox = TRUE)
temp3 <- temp[, (list(group=list(as.list(.SD))))]
jsonlite::toJSON(temp3,pretty = TRUE, auto_unbox = TRUE)
Is there an "easy" solution for my problem?
Thanks
edit more complex example
temp <-
data.table(
id1 = 1:6,
id2 = c(rep("A", 2), rep("B", 2), rep("C", 2)),
data = rep(list(data.table(
a = 1:2, b = 1:2
)), 6),
type = "test"
)
nest1 <- temp[, list(list(.SD)),by=.(id1,id2)] %>% setnames("V1","group")
nest1[, type:="B"]
nest2 <- nest1[, list(list(.SD)),by=.(id2)] %>% setnames("V1","data")
nest2[, type:="C"]
nest3 <- nest2[, list(list(.SD)),by=.(id2)] %>% setnames("V1","group")
jsonlite::toJSON(nest3, pretty = TRUE)
desired output (shortend):
Group should only contain objects and no arrays
[
{
"id2": "A",
"group": {
"data": [
{
"id1": 1,
"group": {
"data": [
{
"a": 1,
"b": 1
},
{
"a": 2,
"b": 2
}
],
"type": "test"
},
"type": "B"
},
{
"id1": 2,
"group": {
"data": [
{
"a": 1,
"b": 1
},
{
"a": 2,
"b": 2
}
],
"type": "test"
},
"type": "B"
}
],
"type": "C"
}
},
{
"id2": "B",
"group": {
"data": [],
"type": "C"
}
}
]
We could use jq to do the unboxing as a post-processing step, since jsonlite doesn't seem to allow for this specific use case:
jsonlite::toJSON(nest3, pretty = TRUE) %>%
jqr::jq('walk(if type=="array" and length==1 then .[0] else . end)')
The jq bit is taken from jq ~ is there a better way to collapse single object arrays?

Leaflet (R) addPopups: coordinates/properties

I'm fairly new to handling spatial data and leaflet in general. I'm having difficulty creating a popup for my map. Basically what I want in the popup is the coordinates of my polygon and one of the properties (the type of class). Below is an test example of my geoJSON file:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"class": "blah"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-81.7987060546875,
32.74570253945518
],
[
-81.6229248046875,
32.16631295696736
],
[
-80.958251953125,
32.4263401615464
],
[
-81.2713623046875,
32.791892438123696
],
[
-81.7437744140625,
32.97180377635759
],
[
-81.7987060546875,
32.74570253945518
]
]
]
}
},
{
"type": "Feature",
"properties": {"class": "blah2"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-82.056884765625,
33.55512901742288
],
[
-81.4471435546875,
33.247875947924385
],
[
-81.40869140625,
33.80653802509606
],
[
-82.078857421875,
33.88865750124075
],
[
-82.40295410156249,
33.58716733904656
],
[
-82.056884765625,
33.55512901742288
]
]
]
}
},
{
"type": "Feature",
"properties": {"class": "blahh3"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-83.485107421875,
32.930318199070534
],
[
-83.07861328125,
31.863562548378965
],
[
-82.21618652343749,
32.11049589629439
],
[
-82.97973632812499,
33.22030778968541
],
[
-83.726806640625,
33.211116472416855
],
[
-83.485107421875,
32.930318199070534
]
]
]
}
}
]
}
Here is the code I have so far to create my map, but I'm struggling/don't even know where to start on creating a popup that includes my coordinates and property:
blahTest <- geojson_read("/file/path/...", what = "sp")
fpal <- colorFactor("viridis", blahTest$class)
leaflet(blahTest) %>%
addTiles() %>%
addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1,
color = ~fpal(class)) %>%
addLegend(colors = ~fpal, opacity = 1.0, labels = ~fpal) %>%
addPopups()
Thanks in advance!
Overview
Using #patL's suggestion, I used the popup parameter within leaflet::addPolygon() function to add label both the class and coordinates that define each polygon within blahTest.
I saved your sample data as .gejson file and imported it using sf::read_sf() and produced the HTML table within the popup using the htmlTable package after reading How to add an html table to leaflet popup.
# load necessary package
library( htmlTable )
library( leaflet )
library( sf )
# load necessary data
blahTest <-
read_sf(
dsn = "test.geojson"
, layer = "OGRGeoJSON"
)
# map data values to colors
fpal <- colorFactor( palette = "viridis", domain = blahTest$class)
# create map
my.map <-
leaflet( data = blahTest ) %>%
addTiles() %>%
addPolygons( stroke = FALSE
, smoothFactor = 0.3
, fillOpacity = 1
, color = ~fpal( class )
, popup = paste0(
"<b>Class: </b>"
, blahTest$class
, "<br>"
, "<b>Coordinates: </b>"
, "<br>"
, lapply(
X = blahTest$geometry
, FUN = function( i )
htmlTable(
x = i[[1]]
, header = c( "Longitude", "Latitude" )
)
)
) ) %>%
addLegend( pal = fpal
, values = ~class
, labels = ~class
, title = "Legend"
, position = "topright"
, opacity = 1.0 )
# view map
my.map
# end of script #

GeoJSON in R Legend

I'm trying to create a leaflet plot with each geographical area a specific color based on a property. Here is an test example of my geojson file:
I'm pretty new to geojson and leaflet in general
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"class": "blah"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-81.7987060546875,
32.74570253945518
],
[
-81.6229248046875,
32.16631295696736
],
[
-80.958251953125,
32.4263401615464
],
[
-81.2713623046875,
32.791892438123696
],
[
-81.7437744140625,
32.97180377635759
],
[
-81.7987060546875,
32.74570253945518
]
]
]
}
},
{
"type": "Feature",
"properties": {"class": "blah2"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-82.056884765625,
33.55512901742288
],
[
-81.4471435546875,
33.247875947924385
],
[
-81.40869140625,
33.80653802509606
],
[
-82.078857421875,
33.88865750124075
],
[
-82.40295410156249,
33.58716733904656
],
[
-82.056884765625,
33.55512901742288
]
]
]
}
},
{
"type": "Feature",
"properties": {"class": "blahh3"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-83.485107421875,
32.930318199070534
],
[
-83.07861328125,
31.863562548378965
],
[
-82.21618652343749,
32.11049589629439
],
[
-82.97973632812499,
33.22030778968541
],
[
-83.726806640625,
33.211116472416855
],
[
-83.485107421875,
32.930318199070534
]
]
]
}
}
]
}
What I want to do is add a legend based off the class properties, such that each different class is associated with a specific color. However, when I try and plot and add the legend I get an error on the plot. Below is my R code:
blahTest <- geojson_read("/file/path/...", what = "sp")
fpal <- colorFactor("viridis", blahTest$class)
leaflet(blahTest) %>%
addTiles() %>%
addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1,
color = ~fpal(class)) %>%
addLegend(colors = ~fpal, opacity = 1.0, labels = ~fpal)
Just some slight modifications to your addLegend argument gives the required output:
# read geojson in r
library(rgdal)
blahTest = readOGR("...", "OGRGeoJSON")
library(leaflet)
# create palette
fpal <- colorFactor(
palette = "viridis",
domain = blahTest$class
)
# plot
leaflet(blahTest) %>%
addTiles() %>%
addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1,
color = ~pal(class)) %>%
addLegend("bottomright",
pal = fpal,
values = ~class,
title = "Legend",
opacity = 1,
labels = ~fpal
)

How to stack Charts with amchart?

is it possible to stack 2 or more graphs in one chart? with the same Scrollbar / Chartcursor?
I tried it with the live editor, but havn't found any option to make this possible.
Here som pictures for explaination:
At the moment i have this graph: http://imgur.com/XpU42xK
But i want a graph like this: http://imgur.com/xdwJ7lu
Thanks for your help :)
Just for the sake of sport I tried to implement it. Good news - it's possible :)
First of all you will need to prepare both charts
First chart
Scrollbar enabled
Chart cursor enabled
Category axis hidden
Legend disabled
Bottom margin: 0
Second chart
Scrollbar disabled
Chart cursor enabled
Category axis enabled
Legend enabled
Top margin: 0
This creates two charts, "glued" together like in your mockup:
Syncing the charts
They still act on their own, like two separate charts. We have to sync them up:
Cursor
Legend
Zoom/pan
That's where this code comes in:
/**
* Use events to sync up cursors and zooms
*/
for ( var x = 0; x < AmCharts.charts.length; x++ ) {
// use "changed" event to track cursor movement on all charts
// place the cursor on other charts on the same index
AmCharts.charts[ x ].addListener( "changed", function( event ) {
// find which category is currently being rolled over
var category = event.chart.dataProvider[ event.index ][ event.chart.categoryField ];
// cycle through all available charts and place the cursor at
// the same category
for ( var i = 0; i < AmCharts.charts.length; i++ ) {
if ( event.chart !== AmCharts.charts[ i ] ) {
AmCharts.charts[ i ].chartCursor.showCursorAt( category );
}
}
} );
// use "zoomed" event to track zooms/pans so we can apply
// the same zoom across other charts
AmCharts.charts[ x ].addListener( "zoomed", function( zoomEvent ) {
// cycle through all available charts and apply same zoom
for ( var i = 0; i < AmCharts.charts.length; i++ ) {
if ( zoomEvent.chart !== AmCharts.charts[ i ] && ( AmCharts.charts[ i ].startIndex != zoomEvent.startIndex || AmCharts.charts[ i ].endIndex != zoomEvent.endIndex ) ) {
AmCharts.charts[ i ].zoomToIndexes( zoomEvent.startIndex, zoomEvent.endIndex );
}
}
} );
}
/**
* Use the last chart to display legend
* We will collect graphs from other charts and mirror them on
* the last chart.
*/
var lastChart = AmCharts.charts[ AmCharts.charts.length - 1 ];
for ( var x = 0; x < ( AmCharts.charts.length - 1 ); x++ ) {
// add graphs
for ( var g = 0; g < AmCharts.charts[ x ].graphs.length; g++ ) {
// create the related graph
var graph = new AmCharts.AmGraph();
graph.lineAlpha = 0;
graph.lineColor = AmCharts.charts[ x ].graphs[ g ].lineColor;
graph.relatedGraph = AmCharts.charts[ x ].graphs[ g ];
graph.valueField = "value_" + x + "_" + g;
graph.showBalloon = false;
graph.includeInMinMax = false;
graph.title = AmCharts.charts[ x ].graphs[ g ].title;
lastChart.addGraph( graph );
// mirror data for rollovers
for ( var i = 0; i < lastChart.dataProvider.length; i++ ) {
lastChart.dataProvider[ i ][ graph.valueField ] = AmCharts.charts[ x ].dataProvider[ i ][ AmCharts.charts[ x ].graphs[ g ].valueField ];
}
}
}
/**
* Add events to the legend of last chart so we can toggle
* graphs of the other charts
*/
lastChart.addListener( "init", function() {
// hide graph
lastChart.legend.addListener( "hideItem", function( event ) {
if ( event.dataItem.relatedGraph !== undefined ) {
event.dataItem.relatedGraph.chart.hideGraph( event.dataItem.relatedGraph );
}
} );
// show graph
lastChart.legend.addListener( "showItem", function( event ) {
if ( event.dataItem.relatedGraph !== undefined ) {
event.dataItem.relatedGraph.chart.showGraph( event.dataItem.relatedGraph );
}
} );
} );
And voila:
Here's a working demo:
/**
* First chart
* With scrollbar
* Without category axis
*/
AmCharts.makeChart( "chartdiv1", {
"type": "serial",
"theme": "light",
"path": "http://www.amcharts.com/lib/3/",
"dataProvider": [ {
"category": "Category #1",
"value": 2025
}, {
"category": "Category #2",
"value": 1882
}, {
"category": "Category #3",
"value": 1809
}, {
"category": "Category #4",
"value": 1322
}, {
"category": "Category #5",
"value": 1122
}, {
"category": "Category #6",
"value": 1114
}, {
"category": "Category #7",
"value": 984
}, {
"category": "Category #8",
"value": 711
}, {
"category": "Category #9",
"value": 665
}, {
"category": "Category #10",
"value": 580
} ],
"valueAxes": [ {
"gridAlpha": 0.2,
"dashLength": 0,
"showFirstLabel": false,
"ignoreAxisWidth": true,
"title": "First graph"
} ],
"startDuration": 1,
"graphs": [ {
"id": "g1",
"lineThickness": 2,
"lineColor": "#f56400",
"type": "step",
"valueField": "value",
"title": "Graph 1"
} ],
"chartCursor": {
"categoryBalloonEnabled": false,
"cursorColor": "#c30000",
"animationDuration": 0
},
"chartScrollbar": {},
"categoryField": "category",
"categoryAxis": {
"ignoreAxisWidth": true,
"labelsEnabled": false,
"axisAlpha": 0
},
"marginBottom": 0,
"marginLeft": 80
} );
/**
* Second chart
* Without scrollbar
* With category axis
*/
AmCharts.makeChart( "chartdiv2", {
"type": "serial",
"theme": "light",
"zoomOutText": "",
"path": "http://www.amcharts.com/lib/3/",
"dataProvider": [ {
"category": "Category #1",
"value": 521
}, {
"category": "Category #2",
"value": 215
}, {
"category": "Category #3",
"value": 655
}, {
"category": "Category #4",
"value": 601
}, {
"category": "Category #5",
"value": 122
}, {
"category": "Category #6",
"value": 114
}, {
"category": "Category #7",
"value": 521
}, {
"category": "Category #8",
"value": 351
}, {
"category": "Category #9",
"value": 222
}, {
"category": "Category #10",
"value": 156
} ],
"valueAxes": [ {
"gridAlpha": 0.2,
"dashLength": 0,
"showLastLabel": false,
"ignoreAxisWidth": true,
"title": "Second graph"
} ],
"startDuration": 1,
"graphs": [ {
"id": "g1",
"lineThickness": 2,
"lineColor": "#fae879",
"type": "step",
"valueField": "value",
"title": "Graph 2"
} ],
"chartCursor": {
"cursorColor": "#c30000",
"animationDuration": 0
},
"categoryField": "category",
"categoryAxis": {
"tickPosition": "middle"
},
"legend": {},
"marginTop": 0,
"marginLeft": 80
} );
/**
* Use events to sync up cursors and zooms
*/
for ( var x = 0; x < AmCharts.charts.length; x++ ) {
// use "changed" event to track cursor movement on all charts
// place the cursor on other charts on the same index
AmCharts.charts[ x ].addListener( "changed", function( event ) {
// find which category is currently being rolled over
var category = event.chart.dataProvider[ event.index ][ event.chart.categoryField ];
// cycle through all available charts and place the cursor at
// the same category
for ( var i = 0; i < AmCharts.charts.length; i++ ) {
if ( event.chart !== AmCharts.charts[ i ] ) {
AmCharts.charts[ i ].chartCursor.showCursorAt( category );
}
}
} );
// use "zoomed" event to track zooms/pans so we can apply
// the same zoom across other charts
AmCharts.charts[ x ].addListener( "zoomed", function( zoomEvent ) {
// cycle through all available charts and apply same zoom
for ( var i = 0; i < AmCharts.charts.length; i++ ) {
if ( zoomEvent.chart !== AmCharts.charts[ i ] && ( AmCharts.charts[ i ].startIndex != zoomEvent.startIndex || AmCharts.charts[ i ].endIndex != zoomEvent.endIndex ) ) {
AmCharts.charts[ i ].zoomToIndexes( zoomEvent.startIndex, zoomEvent.endIndex );
}
}
} );
}
/**
* Use the last chart to display legend
* We will collect graphs from other charts and mirror them on
* the last chart.
*/
var lastChart = AmCharts.charts[ AmCharts.charts.length - 1 ];
for ( var x = 0; x < ( AmCharts.charts.length - 1 ); x++ ) {
// add graphs
for ( var g = 0; g < AmCharts.charts[ x ].graphs.length; g++ ) {
// create the related graph
var graph = new AmCharts.AmGraph();
graph.lineAlpha = 0;
graph.lineColor = AmCharts.charts[ x ].graphs[ g ].lineColor;
graph.relatedGraph = AmCharts.charts[ x ].graphs[ g ];
graph.valueField = "value_" + x + "_" + g;
graph.showBalloon = false;
graph.includeInMinMax = false;
graph.title = AmCharts.charts[ x ].graphs[ g ].title;
lastChart.addGraph( graph );
// mirror data for rollovers
for ( var i = 0; i < lastChart.dataProvider.length; i++ ) {
lastChart.dataProvider[ i ][ graph.valueField ] = AmCharts.charts[ x ].dataProvider[ i ][ AmCharts.charts[ x ].graphs[ g ].valueField ];
}
}
}
/**
* Add events to the legend of last chart so we can toggle
* graphs of the other charts
*/
lastChart.addListener( "init", function() {
// hide graph
lastChart.legend.addListener( "hideItem", function( event ) {
if ( event.dataItem.relatedGraph !== undefined ) {
event.dataItem.relatedGraph.chart.hideGraph( event.dataItem.relatedGraph );
}
} );
// show graph
lastChart.legend.addListener( "showItem", function( event ) {
if ( event.dataItem.relatedGraph !== undefined ) {
event.dataItem.relatedGraph.chart.showGraph( event.dataItem.relatedGraph );
}
} );
} );
.chartdiv {
width: 100%;
height: 300px;
font-size: 11px;
}
<script src="http://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="http://www.amcharts.com/lib/3/serial.js"></script>
<script src="http://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv1" class="chartdiv"></div>
<div id="chartdiv2" class="chartdiv"></div>

Resources