首先,加载recharts:
library(recharts)
和弦图Chord plot包含2个类型:
关键是:
rbind将两者合并。如果未提供节点数据框,recharts会基于联结数据框自动构建。相应地,提供[x, x1, series/relation, weight/value]数据框。echartr(data, x, <y>, <series>, <t>, <type>, <subtype>)
| 参数 | 要求 |
|---|---|
data |
数据框格式的源数据 |
x |
文本型自变量,其他类型转为因子后计算。节点/联结模式下,必须提供 |
y |
数值型应变量。节点/联结模式下,只传入 |
series |
数据系列变量,转为因子后计算。如果提供多个变量,只传入第一个。 |
t |
时间轴变量,转为因子后计算。如提供多个变量,只传入第一个。 |
type |
‘chord’. |
subtype |
|
grpmtx <- matrix(c(11975, 5871, 8916, 2868, 1951, 10048, 2060, 6171, 8010, 16145,
8090, 8045, 1013, 990, 940, 6907), byrow=TRUE, nrow=4)
grpmtx <- as.data.frame(grpmtx)
names(grpmtx) <- paste0('Group', 1:4)
grpmtx$Name <- paste0('Group', 1:4)
knitr::kable(grpmtx, align=c('lllll'))
| Group1 | Group2 | Group3 | Group4 | Name |
|---|---|---|---|---|
| 11975 | 5871 | 8916 | 2868 | Group1 |
| 1951 | 10048 | 2060 | 6171 | Group2 |
| 8010 | 16145 | 8090 | 8045 | Group3 |
| 1013 | 990 | 940 | 6907 | Group4 |
数据框的前四列就是一个矩阵,而最后一列则是名称向量。所以其数据结构符合矩阵模式的要求。
矩阵模式可以转换为节点/联结模式。Matrix[i, j]代表了两个节点(i & j)和一个联结(i -> j)。
knitr::kable(deutsch[deutsch$year==2014,])
| player | club | weight | role | year |
|---|---|---|---|---|
| Kruse | Monchengladbach | 1 | Fw | 2014 |
| Kramer | Monchengladbach | 1 | Mf | 2014 |
| Neuer | Bayern | 1 | Gk | 2014 |
| Boateng | Bayern | 1 | Df | 2014 |
| Lahm | Bayern | 1 | Df | 2014 |
| Kroos | Bayern | 1 | Mf | 2014 |
| Muller | Bayern | 1 | Mf | 2014 |
| Gotze | Bayern | 1 | Fw | 2014 |
| Badstuber | Bayern | 1 | Df | 2014 |
| Hummels | Dortmund | 1 | Df | 2014 |
| Weidenfeller | Dortmund | 1 | Gk | 2014 |
| Reus | Dortmund | 1 | Df | 2014 |
| Gundogan | Dortmund | 1 | Md | 2014 |
数据框内找不到数值型矩阵结构,所以被识别为节点/联结模式。由于第一、二列么有NA,所以recharts会基于所给的数据框构建一个节点数据框。其结构为:
| name | value | series |
|---|---|---|
| Badstuber | 1 | |
| Boateng | 1 | |
| Gotze | 2 | |
| Gundogan | 1 | |
| Howedes | 1 | |
| Hummels | 2 | |
| Kimmich | 1 | |
| Kramer | 1 | |
| Kroos | 2 | |
| Kruse | 1 | |
| Lahm | 1 | |
| Leno | 1 | |
| Meyer | 1 | |
| Muller | 2 | |
| Mustafi | 1 | |
| Neuer | 2 | |
| Ozil | 1 | |
| Reus | 1 | |
| Tah | 1 | |
| Volland | 1 | |
| Weidenfeller | 1 | |
| Arsenal | 2 | |
| Bayern | 11 | |
| Dortmund | 5 | |
| Leverkusen | 3 | |
| Madrid | 1 | |
| Monchengladbach | 2 | |
| Schalke | 2 |
设type为’chord’,subtype为’ribbon’。
echartr(grpmtx, Name, c(Group1, Group2, Group3, Group4),
type='chord', subtype='ribbon + asc + descsub + hidelab + scaletext') %>%
setTitle('Test Data','From d3.js')
设type为’chord’。如果数据结构不包括双向联结,不论是否设置subtype为’ribbon’,都无法显示缎带和弦图。
echartr(deutsch[deutsch$year==2014,], c(club, player), weight, role, type='chord',
sub='asc + descsub + rotatelab') %>%
setTitle('Club Orientation of Deutsch Soccer Team (2014)')
如果要显示缎带和弦图,必须将源数据修改为双向联结。
现在,deutsch14只有单向联结,这意味着,它只定义了Gotze->Bayern的关系,而没有定义反向的Bayern->Gotze。
knitr::kable(with(deutsch[deutsch$year==2014,], table(player, club)))
| Bayern | Dortmund | Monchengladbach | |
|---|---|---|---|
| Badstuber | 1 | 0 | 0 |
| Boateng | 1 | 0 | 0 |
| Gotze | 1 | 0 | 0 |
| Gundogan | 0 | 1 | 0 |
| Hummels | 0 | 1 | 0 |
| Kramer | 0 | 0 | 1 |
| Kroos | 1 | 0 | 0 |
| Kruse | 0 | 0 | 1 |
| Lahm | 1 | 0 | 0 |
| Muller | 1 | 0 | 0 |
| Neuer | 1 | 0 | 0 |
| Reus | 0 | 1 | 0 |
| Weidenfeller | 0 | 1 | 0 |
我们需要复制source和target列以构建一个矩阵。
deutsch14 <- deutsch[deutsch$year==2014,]
deutsch14 <- rbind(deutsch14, deutsch14)
deutsch14[14:26, c('player', 'club')] <- recharts:::exchange(
deutsch14[14:26, 'player'], deutsch14[14:26, 'club'])
knitr::kable(with(deutsch14, table(player, club)))
| Badstuber | Bayern | Boateng | Dortmund | Gotze | Gundogan | Hummels | Kramer | Kroos | Kruse | Lahm | Monchengladbach | Muller | Neuer | Reus | Weidenfeller | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Badstuber | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Bayern | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 |
| Boateng | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Dortmund | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
| Gotze | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Gundogan | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Hummels | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Kramer | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
| Kroos | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Kruse | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
| Lahm | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Monchengladbach | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| Muller | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Neuer | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Reus | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Weidenfeller | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
这样,设置subtype为’ribbon’,就能获得缎带和弦图了。
echartr(deutsch14, c(club, player), weight, role, type='chord',
sub='asc + descsub + rotatelab + ribbon') %>%
setTitle('Club Orientation of Deutsch Soccer Team (2014)')
另一个例子基于预置的数据集mideast。
mideast <- as.data.frame(mideast, col.names=mideast[1,], stringsAsFactors=FALSE)
names(mideast) <- mideast[1,]
mideast <- mideast[2:16,]
me <- data.table::melt(mideast, id=NA)
## Warning in melt_dataframe(data, as.integer(id.ind - 1),
## as.integer(measure.ind - : '.Random.seed' is not an integer vector but of
## type 'NULL', so ignored
me <- me[!is.na(me$value),]
me$series <- strsplit(me$value, '/')
me$value <- sapply(me$series, function(x) as.numeric(x[2]))
me$series <- sapply(me$series, function(x) x[1])
names(me) <- c('source', 'target', 'value', 'series')
str(me)
## 'data.frame': 82 obs. of 4 variables:
## $ source: chr "叙利亚反对派" "阿萨德" "伊朗" "塞西" ...
## $ target: Factor w/ 15 levels "美国","叙利亚反对派",..: 1 1 1 1 1 1 1 1 2 2 ...
## $ value : num 1 1 1 1 1 1 1 1 9 9 ...
## $ series: chr "支持" "反对" "反对" "未表态" ...
echartr(me, c(source, target), value, series, type='chord', sub='ribbon')
用year列作为时间轴。
echartr(deutsch, c(club, player), weight, role, t=year, type='chord',
sub='asc + descsub + rotatelab') %>%
setTimeline(show=FALSE, autoPlay=TRUE) %>%
setTitle('Club Orientation of Deutsch Soccer Team')
接下来可以配置控件、添加标注点/标注线,以及美化成图。
参考相关函数,尽情探索吧。