First, you should load recharts
:
library(recharts)
Map includes 4 basic types:
The keys are:
type
and/or subtype
to display the base mapx
x[,1]
must be valid geographic names, e.g., ‘United States of America’ instead of ‘USA’ or ‘U.S.’.y
y[,1]
: valuey[,2]
: logical, if is selected. Also allowed to use 1 for TRUE, 0 for FALSE.addNameMap
for geoName mapping/translation;addHeatMap
for additional heatmap graph layeraddMarkLine
or addMarkPoint
to add markLines and/or markPoints
addGeoCoord
to define coordinates of the places for markLine and markPointechartr(data, <x>, <y>, <series>, <facet>, <lng>, <lat>, <t>, <type>, <subtype>)
Arg | Requirement |
---|---|
data |
source data in the form of data.frame |
x |
character independent variable. Other type will be coerced to factors. Only the first one is accepted if multiple variables are provided. |
y |
numeric dependent variable. Only the first 2 are accepted if multiple variables are provided. |
series |
series variable which will be coerced to factors. Each level of |
facet |
facetting variable which will be coerced to factors. Each level of |
t |
timeline variable which will be coerced to factors. Only the first one is accepted if multiple variables are provided. |
type |
‘map_world’, ‘map_world_multi’, ‘map_china’, ‘map_china_multi’. |
subtype |
|
If you leave all params NULL except for type
and/or subtype
, you will get a base map with no data shown.
Set type
‘map_world’ or ‘map_china’. Leave all other params NULL.
echartr(NULL, type='map_world') %>% setTitle('World Map')
echartr(NULL, type='map_china') %>% setTitle('China Map')
You can also display partial maps. Political zones of China can act as the independent mapType, so you can see its subordinate areas.
echartr(NULL, type='map_world', subtype='United States of America') %>%
setTitle('World Map|USA')
echartr(NULL, type='map_china', subtype='上海') %>%
setTitle('China Map|Shanghai')
Set type
‘map_world_multi’ or ‘map_china_multi’, you will get a base map for multiple selection. You can also apply subtypes to it.
echartr(NULL, type='map_world_multi') %>% setTitle('World Map')
echartr(NULL, type='map_china_multi', subtype='上海') %>%
setTitle('China Map|Shanghai')
If you assign facet
and subtype
with valid geographic names, you will yield separated multiple maps. Note that subtype
must be wrapped as list.
data <- data.frame(x=c('United States of America', 'China', 'Japan'))
echartr(data, x, facet=x, type='map_world', subtype=as.list(data$x))
You can attach data onto the base map to render it more informative.
If no series
is assigned, the map does not differentiate data series.
worldgdp <- data.frame(
country=c('United States of America', 'China', 'Japan', 'Germany',
'United Kingdom', 'France', 'Brazil', 'Italy', 'India','Russia',
'Canada', 'Australia', 'South Korea', 'Spain', 'Mexico',
'Indonesia', 'Netherlands', 'Turkey', 'Saudi Arabia',
'Switzerland'),
GDP=c(17418925, 10380380, 4616335, 3859547, 2945146, 2846889, 2353025,
2147952, 2049501, 1857461, 1788717, 1444189, 1416949, 1406855, 1282725,
888648, 866354, 806108, 752459, 712050))
echartr(worldgdp, country, GDP, type="map_world") %>%
setTitle("World GDP Top 20, 2014")
But point markers are not that informative. Let’s color the areas by mapping the data to dataRange. Plus, set it ‘move’ and ‘scale’.
echartr(worldgdp, country, GDP, type="map_world", subtype="move + scale") %>%
setDataRange(splitNumber=0, color=getColFromPal('rainbow')) %>%
setTitle("World GDP Top 20, 2014")
Let’s use ChinaGDP
dataset with ‘Year’ as data series variable.
str(ChinaGDP)
## 'data.frame': 93 obs. of 3 variables:
## $ Year: num 2014 2014 2014 2014 2014 ...
## $ Prov: chr "广东" "江苏" "山东" "浙江" ...
## $ GDP : num 1103605 1059587 967419 653668 568786 ...
totGDP <- data.table::dcast(ChinaGDP, Prov~., sum, value.var='GDP')
## Warning in split_indices(.group, .n): '.Random.seed' is not an integer
## vector but of type 'NULL', so ignored
ChinaGDP <- ChinaGDP[order(ChinaGDP$Year),]
echartr(ChinaGDP, Prov, GDP, Year, type="map_china") %>%
setDataRange(splitNumber=0, valueRange=range(totGDP[, 2]),
color=c('red','orange','yellow','limegreen','green')) %>%
setTitle("China GDP by Provice, 2012-2014")
This applies ‘sum’ as mapvalueCalculation
method. Add ‘average’ to subtype
to change the method to ‘avarge’.
echartr(ChinaGDP, Prov, GDP, Year, type="map_china", subtype='average') %>%
setDataRange(splitNumber=0,
color=c('red','orange','yellow','limegreen','green')) %>%
setTitle("China GDP by Provice, 2012-2014")
Put ‘Year’ as t
, we will get a map with timeline.
echartr(ChinaGDP, Prov, GDP, t=Year, type="map_china", subtype='average') %>%
setDataRange(splitNumber=0,
color=c('red','orange','yellow','limegreen','green')) %>%
setTitle("China GDP by Provice, 2012-2014")
Just set type
‘map_world_multi’ or ‘map_china_multi’. The rest are similar to above.
Let’s tile the countries with top 10 GDP on the chart rather than showing them where they are.
worldgdp <- worldgdp[order(worldgdp$GDP, decreasing=TRUE),]
worldgdp10 <- worldgdp[1:10, ]
echartr(worldgdp10, country, GDP, facet=country, type='map_world',
subtype=as.list(worldgdp10$country)) %>%
setDataRange(color=c(
'red', 'orange', 'yellow', 'limegreen', 'green'), pos=4) %>%
setSymbols('none')
Then you can configure the widgets, add markLines and/or markPoints, fortify the chart.
Maybe you want to show the China province names in English. You can use addNameMap
or overideNameMap
function.
There is a preinstalled dataset geoNameMap listing some Chinese and English geographic names. ‘LEVEL’ is a number ranging from 0 to 3: 0 reprensents country, 1 reprensents province, 2 reprensents city, and, 3 reprensents county. ‘FKEY’ is foreign key of the parent level. E.g., ‘China’ is in the record with ID 31, so we can get all the China provinces by geoNameMap[geoNameMap$FKEY==31,]
.
str(geoNameMap)
## 'data.frame': 3735 obs. of 5 variables:
## $ ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ EN : chr "Afghanistan" "Angola" "Albania" "United Arab Emirates" ...
## $ CN : chr "阿富汗" "安哥拉" "阿尔巴尼亚" "阿联酋" ...
## $ FKEY : int 0 0 0 0 0 0 0 0 0 0 ...
## $ LEVEL: int 0 0 0 0 0 0 0 0 0 0 ...
So we prepare a two-column dictionary of the geographic names: Col 1 is the name in the source language, Col 2 is that in the target language. That’s the valid data structure addNameMap
requires.
dict <- geoNameMap[geoNameMap$FKEY==31, c("CN", "EN")]
echartr(NULL, type="map_china_multi") %>% addNameMap(dict, mode='overide')
addMarkLine
Based on a base map, we can add markLines using addMarkLine
(or addML
for short) or overideMarkLine
.
This instance makes use of another preinstalled dataset flight.
str(flight)
## List of 2
## $ route:'data.frame': 150 obs. of 2 variables:
## ..$ From: chr [1:150] "北京" "北京" "北京" "北京" ...
## ..$ To : chr [1:150] "包头" "北海" "广州" "郑州" ...
## $ coord:'data.frame': 114 obs. of 3 variables:
## ..$ Place: chr [1:114] "上海" "东莞" "东营" "中山" ...
## ..$ Lng : num [1:114] 121 114 119 113 111 ...
## ..$ Lat : num [1:114] 31.3 22.9 37.6 22.5 36.2 ...
route <- flight$route
names(route) <- c('name1', 'name2')
coord <- flight$coord
g <- echartr(NULL, type='map_china') %>%
addML(series='北京', data=route[route$name1=='北京',]) %>%
addML(series='上海', data=route[route$name1=='上海',]) %>%
addML(series='广州', data=route[route$name1=='广州',])
g
It is equivalent to
g <- echartr(NULL, type='map_china') %>%
addML(series=c('北京', '上海', '广州), data=route)
addGeoCoord
But the markLines are not shown yet. You have to append the longitudes and latitudes of the places ever appear in the markLine dataset using addGeoCoord
.
g %>% addGeoCoord(coord)
addMarkPoint
Based on a base map, we can add markLines using addMarkPoint
(or addMP
for short) or overideMarkPoint
.
This instance makes use of another preinstalled dataset chinapm25.
str(chinapm25)
## 'data.frame': 190 obs. of 4 variables:
## $ City : chr "海门" "鄂尔多斯" "招远" "舟山" ...
## $ Value: num 9 12 12 12 14 15 16 18 18 19 ...
## $ Lng : num 121 110 120 122 124 ...
## $ Lat : num 31.9 39.6 37.4 30 47.3 ...
names(chinapm25) <- c('name', 'value', 'lng', 'lat')
g <- echartr(NULL, type='map_china') %>%
addMP(data=chinapm25[,c('name', 'value')], symbolSize=5, itemStyle=list(
normal=list(borderColor='#87cefa', borderWidth=1,
label=list(show=FALSE)),
emphasis=list(borderColor='#1e90ff', borderWidth=5,
label=list(show=FALSE))
)) %>%
addMP(series='Top 5',
data=data.frame(
name=c('廊坊', '合肥', '菏泽', '武汉', '大庆'),
value=c(193, 194, 229, 273, 279)),
symbol='emptyCircle',
symbolSize=JS('function (v) {return 10 + v/100;}'),
effect=list(show=TRUE)
) %>%
setDataRange(splitNumber=0, valueRange=c(0, 500), color=c(
'maroon', 'purple', 'red', 'orange', 'yellow', 'lightgreen'))
g
addGeoCoord
Although recharts
can recognize most of the cities, there still might be points missing coordinates. Again, we need to define the geoCoord using addGeoCoord
.
addGeoCoord
requires a data.frame with three columns in order: name
, longitude
and latitude
. Pay attention to the order of lng
and lat
.
g %>% addGeoCoord(chinapm25[,c('name', 'lng', 'lat')]) %>%
setTitle('PM2.5 in China Cities', 'Fictious Data')
What if I don’t know the coordinates of the places? You need geocode
(forked from geoChina), which queries info from Google (so first you should be able to visit Google) or Baidu (in this way you need to provide Baidu api key).
geocode(c('北京', '上海'), api='google')
## lat lng
## 1 39.90281 116.4012
## 2 31.23236 121.4692
or geocode(c('北京', '上海'), api='baidu', key='xxxxx')
.
These are coordinates under WGS-84 system. If you want to apply them in Echarts, you need to convert them to BD-09 system. You can use convWGS2BD
function or use geocode
with ocs
=‘BD-09’ to do that.
convWGS2BD(geocode(c('北京', '上海'), api='google'))
## lat lng
## 1 39.91053 116.4138
## 2 31.23636 121.4803
or geocode(c('北京', '上海'), api='google', ocs='BD-09')
addMarkLine
And addMarkPoint
In addition to the addMarkLine
example, we addMarkPOint
to yield the Fictious Baidu Migration example.
route <- flight$route
names(route) <- c('name1', 'name2')
coord <- flight$coord
target <- data.frame(
name1=c(rep('北京', 10), rep('上海', 10), rep('广州', 10)),
name2=c(
"上海","广州","大连","南宁","南昌","拉萨","长春","包头","重庆","常州",
"包头","昆明","广州","郑州","长春","重庆","长沙","北京","丹东","大连",
"福州","太原","长春","重庆","西安","成都","常州","北京","北海","海口"),
value=c(95,90,80,70,60,50,40,30,20,10,95,90,80,70,60,50,40,30,20,10,95,90,
80,70,60,50,40,30,20,10))
# series column mapping series of addML/addMP
target$series <- paste0(target$name1, 'Top10')
## apply addGeoCoord, and add markLines without values
g <- echartr(NULL, type='map_china') %>% addGeoCoord(coord) %>%
addML(series=1, data=route, symbol=c('none', 'circle'), symbolSize=1,
smooth=TRUE, itemStyle=list(normal=itemStyle(
color='#fff', borderWidth=1, borderColor='rgba(30,144,255,0.5)')))
## modify itemStyle of the base map to align the areaStyle with bgColor and
## disable `hoverable`
g <- g %>% setSeries(hoverable=FALSE, itemStyle=list(
normal=itemStyle(
borderColor='rgba(100,149,237,1)', borderWidth=0.5,
areaStyle=areaStyle(color='#1b1b1b'))
))
g
## add markLines with values
line.effect <- list(
show=TRUE, scaleSize=1, period=30, color='#fff', shadowBlur=10)
line.style <- list(normal=itemStyle(
borderWidth=1, lineStyle=lineStyle(type='solid', shadowBlur=10)))
g1 <- g %>%
addML(series=c('北京Top10', '上海Top10', '广州Top10'), data=target,
smooth=TRUE, effect=line.effect, itemStyle=line.style)
g1
## add markPoints
## series better be 2, 3, 4 rather than the series names
jsSymbolSize <- JS('function (v) {return 10+v/10;}')
mp.style <- list(normal=itemStyle(label=labelStyle(show=FALSE)),
emphasis=itemStyle(label=labelStyle(position='top')))
g2 <- g1 %>%
addMP(series=2:4, data=target[,c("name2", "value", "series")],
effect=list(show=TRUE), symbolSize=jsSymbolSize,
itmeStyle=mp.style)
g2
## setDataRange
g3 <- g2 %>%
setDataRange(
color=c('#ff3333', 'orange', 'yellow','limegreen','aquamarine'),
valueRange=c(0, 100), textStyle=list(color='#fff'),
splitNumber=0)
## setTheme
g3 <- g3 %>% setLegend(pos=10, selected='上海Top10', textStyle=list(color='#fff')) %>%
setTheme(palette=c('gold','aquamarine','limegreen'), bgColor='#1b1b1b') %>%
setToolbox(pos=3) %>%
setTitle('Baidu Migration', 'Fictious Data', pos=12,
textStyle=list(color='white'))
g3
Let’s make up a fictious heatmap dataset. The dataset must be comprised of lng
, lat
and heat value
.
heatmap <- sapply(1:15, function(i){
x <- 100 + runif(1, 0, 1) * 16
y <- 24 + runif(1, 0, 1) * 12
lapply(0:floor(50 * abs(rnorm(1))), function(j){
c(x+runif(1, 0, 1)*2, y+runif(1, 0, 1)*2, runif(1, 0, 1))
})
})
heatmap <- data.frame(matrix(unlist(heatmap), byrow=TRUE, ncol=3))
str(heatmap)
## 'data.frame': 531 obs. of 3 variables:
## $ X1: num 109 108 102 102 102 ...
## $ X2: num 35.7 34.9 27.5 27.9 27.9 ...
## $ X3: num 0.967 0.47 0.934 0.698 0.863 ...
Then append/modify the heatmap to a base map using addHeatmap
/ overideHeatmap
.
echartr(NULL, type="map_china") %>% addHeatmap(data=heatmap)
You can refer to related functions to play around on your own.