-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy path07-flow.Rmd
2265 lines (1744 loc) · 93.8 KB
/
07-flow.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Flow {#flow}
---
```{r flow-network-graph-intro-image, echo=FALSE, fig.align='center', fig.cap="Network Graph Layout", out.width = '50%'}
knitr::include_graphics("https://www.r-graph-gallery.com/247-network-chart-layouts_files/figure-html/thecode8-1.png")
```
## Arc Diagram
#### Definition
An [arc diagram](https://www.data-to-viz.com/graph/arc.html#definition) is a special kind of [network graph](https://www.data-to-viz.com/graph/network.html). It is constituted by nodes that represent entities and by `links` that show relationships between entities. In arc diagrams, nodes are displayed along a `single axis` and links are represented with arcs.
Here is a simple example. Five links between 6 nodes are represented using a [2d network diagram](https://www.data-to-viz.com/graph/network.html) (left) and an arc diagram (right)
```{r arc-diagram, echo=TRUE, message=FALSE, warning=FALSE}
# Libraries
library(tidyverse)
library(viridis)
library(patchwork)
library(hrbrthemes)
library(igraph)
library(ggraph)
library(colormap)
# A really simple edge list
links=data.frame(
source=c("A", "A", "A", "A", "B"),
target=c("B", "C", "D", "F","E")
)
# Transform to a igraph object
mygraph <- graph_from_data_frame(links)
# Make the usual network diagram
p1 <- ggraph(mygraph) +
geom_edge_link(edge_colour="black", edge_alpha=0.3, edge_width=0.2) +
geom_node_point( color="#69b3a2", size=5) +
geom_node_text( aes(label=name), repel = TRUE, size=8, color="#69b3a2") +
theme_void() +
theme(
legend.position="none",
plot.margin=unit(rep(2,4), "cm")
)
# Make a cord diagram
p2 <- ggraph(mygraph, layout="linear") +
geom_edge_arc(edge_colour="black", edge_alpha=0.3, edge_width=0.2) +
geom_node_point( color="#69b3a2", size=5) +
geom_node_text( aes(label=name), repel = FALSE, size=8, color="#69b3a2", nudge_y=-0.1) +
theme_void() +
theme(
legend.position="none",
plot.margin=unit(rep(2,4), "cm")
)
p1 + p2
```
### Arc Diagrams
Are not as good as 2d network charts to convey the overall node structure. It has 2 main advantages tough:
* It can highlight clusters and bridges quite well if the node order is optimized.
* It allows to display the label of each node, which is often impossible in 2d structure.
Here is an example showing the co-authorship network of a researcher. Vincent Ranwez is author of several scientific publications and counts more than 100 co-authors, all represented by a node on the following chart. If two people have already been on the same paper, they are linked by an arc.
```{r arc-diagrams-detail, echo=TRUE, message=FALSE, warning=FALSE}
# Load data
dataUU <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/13_AdjacencyUndirectedUnweighted.csv", header=TRUE)
# Transform the adjacency matrix in a long format
connect <- dataUU %>%
gather(key="to", value="value", -1) %>%
mutate(to = gsub("\\.", " ",to)) %>%
na.omit()
# Number of connection per person
c( as.character(connect$from), as.character(connect$to)) %>%
as.tibble() %>%
group_by(value) %>%
summarize(n=n()) -> coauth
colnames(coauth) <- c("name", "n")
#dim(coauth)
# Create a graph object with igraph
mygraph <- graph_from_data_frame( connect, vertices = coauth, directed = FALSE )
# Find community
com <- walktrap.community(mygraph)
#max(com$membership)
#Reorder dataset and make the graph
coauth <- coauth %>%
mutate( grp = com$membership) %>%
arrange(grp) %>%
mutate(name=factor(name, name))
# keep only 10 first communities
coauth <- coauth %>%
filter(grp<16)
# keep only this people in edges
connect <- connect %>%
filter(from %in% coauth$name) %>%
filter(to %in% coauth$name)
# Create a graph object with igraph
mygraph <- graph_from_data_frame( connect, vertices = coauth, directed = FALSE )
# prepare a vector of n color in the viridis scale
mycolor <- colormap(colormap=colormaps$viridis, nshades=max(coauth$grp))
mycolor <- sample(mycolor, length(mycolor))
# Make the graph
ggraph(mygraph, layout="linear") +
geom_edge_arc(edge_colour="black", edge_alpha=0.2, edge_width=0.3, fold=TRUE) +
geom_node_point(aes(size=n, color=as.factor(grp), fill=grp), alpha=0.5) +
scale_size_continuous(range=c(0.5,8)) +
scale_color_manual(values=mycolor) +
geom_node_text(aes(label=name), angle=65, hjust=1, nudge_y = -1.1, size=2.3) +
theme_void() +
theme(
legend.position="none",
plot.margin=unit(c(0,0,0.4,0), "null"),
panel.spacing=unit(c(0,0,3.4,0), "null")
) +
expand_limits(x = c(-1.2, 1.2), y = c(-5.6, 1.2))
```
### Common Mistakes
The order of nodes is the key for arc diagrams. See the following figure showing the same arc diagram than above, but with nodes displayed in a random order. Harder to find any insight isn't it?
```{r arc-diagram-common-mistakes, echo=TRUE, message=FALSE, warning=FALSE}
#Reorder dataset randomly
coauth <- coauth %>%
slice( sample(c(1:nrow(coauth)), nrow(coauth)))
# Create a graph object with igraph
mygraph <- graph_from_data_frame( connect, vertices = coauth, directed = FALSE )
# prepare a vector of n color in the viridis scale
mycolor <- colormap(colormap=colormaps$viridis, nshades=max(coauth$grp))
mycolor <- sample(mycolor, length(mycolor))
# Make the graph
ggraph(mygraph, layout="linear") +
geom_edge_arc(edge_colour="black", edge_alpha=0.2, edge_width=0.3, fold=TRUE) +
geom_node_point(aes(size=n, color=as.factor(grp), fill=grp), alpha=0.5) +
scale_size_continuous(range=c(0.5,8)) +
scale_color_manual(values=mycolor) +
geom_node_text(aes(label=name), angle=65, hjust=1, nudge_y = -1.1, size=2.3) +
theme_void() +
theme(
legend.position="none",
plot.margin=unit(c(0,0,0.4,0), "null"),
panel.spacing=unit(c(0,0,3.4,0), "null")
) +
expand_limits(x = c(-1.2, 1.2), y = c(-5.6, 1.2))
```
## Chord Diagram
---
A [Chord diagram](https://www.data-to-viz.com/graph/chord.html) allows to study flows between a set of entities. Entities (nodes) are displayed all around a circle and connected with arcs (links). In `R`, the `circlize` package is the best option to build it.
The circlize package allows to build all kinds of circular chart. This first section introduces the way it works, step by step. Chord diagram are described in the following section, but a basic understanding of the library is necessary at first.
### Introduction to the `circlize` Package
This section is an introduction to the `circlize` package: the ultimate way to build [circular charts](https://www.r-graph-gallery.com/chord-diagram.html) with R. It shows how to initialize a circular section and fill it with a [scatterplot](https://www.r-graph-gallery.com/scatterplot.html).
In R, circular plots are made using the `circlize` package. Circular plots are composed by several regions (8 here), each representing a level of a factor. Three steps are required to build a circular plot:
* *Step 1*: Initialize the chart with `circos.initialize()`. Provide the factor vector, and the numeric values to use for the X axis. The circle will be split in as many zone as the number of levels present in your factor. Each region will be as long as the coresponding x axis.
* *Step 2*: Build the regions with `circos.trackPlotRegion()`. You have to specify the factors once again, and tell what to use for the Y axis if needed.
* *Step 3*: Add a chart in each region. Here `circos.trackPoints()` is used to build a scatterplot. See [chart #226](https://www.r-graph-gallery.com/226-plot-types-for-circular-plot.html) for other chart types.
```{r chord-diagram, echo=TRUE, message=FALSE, warning=FALSE}
# Upload library
library(circlize)
# Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Step1: Initialise the chart giving factor and x-axis.
circos.initialize( factors=data$factor, x=data$x )
# Step 2: Build the regions.
circos.trackPlotRegion(factors = data$factor, y = data$y, panel.fun = function(x, y) {
circos.axis()
})
# Step 3: Add points
circos.trackPoints(data$factor, data$x, data$y, col = "blue", pch = 16, cex = 0.5)
```
### Circular Chart Customization for the `Circlize` R package
This post follows the previous [introduction](https://www.r-graph-gallery.com/224-basic-circular-plot.html) to the `circlize` package. It shows how to apply basic customizations to a circular chart: how to change track width, background color, start angle and more.
### Most Basic Circular Chart
Let's remind how to build a basic circular chart with the `circlize` package.
This is extensively described in [chart #224](https://www.r-graph-gallery.com/224-basic-circular-plot.html).
```r
# Upload library
library(circlize)
# Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Step1: Initialise the chart giving factor and x-axis.
circos.initialize( factors=data$factor, x=data$x )
# Step 2: Build the regions.
circos.trackPlotRegion(factors = data$factor, y = data$y, panel.fun = function(x, y) {
circos.axis()
})
# Step 3: Add points
circos.trackPoints(data$factor, data$x, data$y)
```
![](https://www.r-graph-gallery.com/225-circular-plot-custom-a-track_files/figure-html/thecode-1.png)
### Customization
Customization can happen at 3 different levels:
* Initialization: use the usual `par()` and the specific `circos.par()` functions for general stuff.
* In `circos.axis()` to customize axis.
* In `circos.trackPoints()` to customize the chart shapes.
Note that most of the parameters are consistent with base R. Have a look to the [scatterplot](https://www.r-graph-gallery.com/scatterplot.html) section of the gallery for more customization.
```r
# Upload library
library(circlize)
# Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# General Customization:
par(
mar = c(1, 1, 1, 1), # Margin around chart
bg = rgb(0.4,0.1,0.7,0.05) # background color
)
circos.par("track.height" = 0.6) # track hight, 0.6 = 60% of total height
# Step1: Initialise the chart giving factor and x-axis.
circos.initialize( factors=data$factor, x=data$x )
# Step2: Build regions.
circos.trackPlotRegion(factors = data$factor, y = data$y, panel.fun = function(x, y) {
circos.axis(
h="top", # x axis on the inner or outer part of the track?
labels=TRUE, # show the labels of the axis?
major.tick=TRUE, # show ticks?
labels.cex=0.5, # labels size (higher=bigger)
labels.font=1, # labels font (1, 2, 3 , 4)
direction="outside", # ticks point to the outside or inside of the circle ?
minor.ticks=4, # Number of minor (=small) ticks
major.tick.percentage=0.1, # The size of the ticks in percentage of the track height
lwd=2 # thickness of ticks and x axis.
)
})
# Step 3: Add points
circos.trackPoints(data$factor, data$x, data$y, col = "#69b3a2", pch = 16, cex = 0.5)
```
![](https://www.r-graph-gallery.com/225-circular-plot-custom-a-track_files/figure-html/thecode2-1.png)
### Available Circular Chart Types with Circlize
The `circlize` package allows to build [circular charts](https://www.r-graph-gallery.com/chord-diagram.html) with R. Several chart types are offered: **bar**, **scatter**, **line**, **abline** and more. This section shows how to build them.
#### Circular Scatterplot
Circular scatterplot has already been extensively described in chart [#224](https://www.r-graph-gallery.com/224-basic-circular-plot.html) and [#225](https://www.r-graph-gallery.com/225-circular-plot-custom-a-track.html).
```r
# Upload library
library(circlize)
circos.par("track.height" = 0.4)
# Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Step1: Initialise the chart giving factor and x-axis.
circos.initialize( factors=data$factor, x=data$x )
# Step 2: Build the regions.
circos.trackPlotRegion(factors = data$factor, y = data$y, panel.fun = function(x, y) {
circos.axis()
})
# Step 3: Add points
circos.trackPoints(data$factor, data$x, data$y, col="#69b3a2")
```
![](https://www.r-graph-gallery.com/226-plot-types-for-circular-plot_files/figure-html/thecode-1.png)
### Circular Line Chart
It is possible to switch to line chart using the `circos.trackLines()` function. Visit the [line chart](https://www.r-graph-gallery.com/line-plot.html) section of the gallery to learn how to customize that kind of chart.
```r
# Upload library
library(circlize)
circos.par("track.height" = 0.4)
# Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Step1: Initialise the chart giving factor and x-axis.
circos.initialize( factors=data$factor, x=data$x )
# Step 2: Build the regions.
circos.trackPlotRegion(factors = data$factor, y = data$y, panel.fun = function(x, y) {
circos.axis()
})
# Step 3: Add points
circos.trackLines(data$factor, data$x[order(data$x)], data$y[order(data$x)], col = rgb(0.1,0.5,0.8,0.3), lwd=2)
```
![](https://www.r-graph-gallery.com/226-plot-types-for-circular-plot_files/figure-html/thecode2-1.png)
### Vertical Ablines
The `circos.trackLines()` function can also be used to display vertical ablines.
```r
# Upload library
library(circlize)
circos.par("track.height" = 0.4)
# Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Step1: Initialise the chart giving factor and x-axis.
circos.initialize( factors=data$factor, x=data$x )
# Step 2: Build the regions.
circos.trackPlotRegion(factors = data$factor, y = data$y, panel.fun = function(x, y) {
circos.axis()
})
# Step 3: Add points
circos.trackLines(data$factor, data$x[order(data$x)], data$y[order(data$x)], col = rgb(0.1,0.5,0.8,0.3), lwd=2, type="h")
```
![](https://www.r-graph-gallery.com/226-plot-types-for-circular-plot_files/figure-html/thecode3-1.png)
### Circular Histogram
Note that each plot type must be coherent with what you specified in the `circos.trackPlotRegion` function.
You have to specify an Y axis for a scatterplot as seen before. But not for a histogram that is built with `circos.trackHist()`.
```r
# Upload library
library(circlize)
circos.par("track.height" = 0.4)
# Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Step1: Initialise the chart giving factor and x-axis.
circos.initialize( factors=data$factor, x=data$x )
circos.trackHist(data$factor, data$x, bg.col = "white", col = "#69b3a2")
```
![](https://www.r-graph-gallery.com/226-plot-types-for-circular-plot_files/figure-html/thecode4-1.png)
### Circular Chart with Several Tracks
The `circlize` package allows to build [circular charts](https://www.r-graph-gallery.com/chord-diagram.html) with several tracks. This section describes how, providing explanation and reproducible code. If you read the graph #224, and #225 you know how to make circular plots and customize them.
If you read the graph [#224](https://www.r-graph-gallery.com/224-basic-circular-plot.html), and [#225](https://www.r-graph-gallery.com/225-circular-plot-custom-a-track.html) you know how to make circular plots and customize them.
It is possible to add several tracks on your circular plot: just repeat the step 2 (building regions with `circos.trackPlotRegion`) and 3 (adding dots with `circos.trackPoints` for instance).
Note that you can custom the width of each track using `track.height`.
```r
#library
library(circlize)
circos.clear()
#Create data
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
#Initialize the plot.
par(mar = c(1, 1, 1, 1) )
circos.initialize(factors = data$factor, x = data$x )
# Build the regions of track #1
circos.trackPlotRegion(factors = data$factor, y=data$y, panel.fun = function(x, y) {
circos.axis(labels.cex=0.5, labels.font=1, lwd=0.8)
})
# --> Add a scatterplot on it:
circos.trackPoints(data$factor, data$x, data$y, col = rgb(0.1,0.5,0.8,0.3), pch=20)
# Build the regions of track #2:
circlize::circos.trackPlotRegion(factors = data$factor, y=data$y, panel.fun = function(x, y) {
circos.axis(labels=FALSE, major.tick=FALSE)
})
# --> Add a scatterplot on it
circos.trackPoints(data$factor, data$x, data$y, col = rgb(0.9,0.5,0.8,0.3), pch=20, cex=2)
# Add track #3 --> don't forget you can custom the height of tracks!
circos.par("track.height" = 0.4)
circos.trackPlotRegion(factors = data$factor, y=data$y, panel.fun = function(x, y) {
circos.axis(labels=FALSE, major.tick=FALSE)
})
circos.trackLines(data$factor, data$x, data$y, col = rgb(0.9,0.5,0.1,0.3), pch=20, cex=2, type="h")
# and continue as long as needed!
```
![](https://www.r-graph-gallery.com/227-add-several-tracks_files/figure-html/thecode-1.png)
### Display Several Chord Diagrams on same Figure
Here is a trick to display several chord diagrams on the same figure, using R and the `circlize` package.
To arrange several circular charts in the same layout, simply use the `layout()` function as shown below.
This example comes from the circlize package [vignette](https://jokergoo.github.io/circlize_book/book/).
```r
# library
library(circlize)
# Arrange the layout
layout(matrix(1:9, 3, 3))
# A loop to create 9 circular plots
for(i in 1:9) {
par(mar = c(0.5, 0.5, 0.5, 0.5), bg=rgb(1,1,1,0.1) )
factors = 1:8
circos.par(cell.padding = c(0, 0, 0, 0))
circos.initialize(factors, xlim = c(0, 1))
circos.trackPlotRegion(ylim = c(0, 1), track.height = 0.05, bg.col = rand_color(8), bg.border = NA )
# add links
for(i in 1:20) {
se = sample(1:8, 2)
circos.link(se[1], runif(2), se[2], runif(2), col = rand_color(1, transparency = 0.4))
}
circos.clear()
}
```
![](https://www.r-graph-gallery.com/229-several-circular-plots-in-a-figure_files/figure-html/thecode-1.png)
### Draw Part of the Circular Chart Only
The `circlize` package allows to display only a section of the circular chart, using the `circos.par()` function.
It is possible to draw only a part of a Circular plot. Use `canvas.xlim` and `canvas.ylim` to specify the zone you want to show, as in the script below.
```r
# library
library(circlize)
# Create data
factors <- letters[1:4]
x1 <- runif(100)
y1 <- runif(100)
# general parameter of the plot.
# With canvas.xlim and canvas.ylim we kind of "zoom on a part of the plot:
par(mar = c(1, 2, 0.1, 0.1) )
circos.par("track.height" = 0.7, "canvas.xlim" = c(0, 1), "canvas.ylim" = c(0, 1), "gap.degree" = 0, "clock.wise" = FALSE)
# Make the usual plot, but with no border
circos.initialize(factors = factors, xlim = c(0, 1))
circos.trackPlotRegion(factors = factors, ylim = c(0, 1), bg.border = NA )
# Finally we plot only the firs sector, so let's change its border to "black" to see it
circos.updatePlotRegion(sector.index = "a", bg.border = "grey" , bg.lwd=0.2)
# Now we can add a plot in this section! You can repeat these steps to add several regions
circos.lines(x1, y1, pch = 16, cex = 0.5, type="h" , col="#69b3a2" , lwd=3)
# Add axis
circos.axis(h="bottom" , labels.cex=0.4, direction = "inside" )
#clear
circos.clear()
```
![](https://www.r-graph-gallery.com/230-draw-part-of-the-circular-plot-only_files/figure-html/thecode-1.png)
Chart [#224](https://www.r-graph-gallery.com/224-basic-circular-plot.html), and [#225](https://www.r-graph-gallery.com/225-circular-plot-custom-a-track.html) introduced the `circlize` package and its ability to build circular charts.
It is possible to add connections between tracks with `circos.links()`.
See chart [#122](https://www.r-graph-gallery.com/122-a-circular-plot-with-the-circlize-package.html) for a customized version, and chart [#123](https://www.r-graph-gallery.com/123-circular-plot-circlize-package-2.html) for an automatized version.
```r
# library
library(circlize)
# Create data
set.seed(123)
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Initialize the plot.
par(mar = c(1, 1, 1, 1) )
circos.initialize(factors = data$factor, x = data$x )
# Build the regions of track #1
circos.trackPlotRegion(factors = data$factor, y=data$y , bg.col = rgb(0.1,0.1,seq(0,1,0.1),0.4) , bg.border = NA)
# Add a link between a point and another
circos.link("a", 0, "b", 0, h = 0.4)
# Add a link between a point and a zone
circos.link("e", 0, "g", c(-1,1), col = "green", lwd = 2, lty = 2, border="black" )
# Add a link between a zone and another
circos.link("c", c(-0.5, 0.5), "d", c(-0.5,0.5), col = "red", border = "blue", h = 0.2)
```
![](https://www.r-graph-gallery.com/228-add-links-between-regions_files/figure-html/thecode-1.png)
### Advanced Chord Diagram with R and Circlize
[Chord diagram](https://www.r-graph-gallery.com/chord-diagram.html) is an efficient way to display flows between entities. This section shows how to build it from an edge list or from an adjacency matrix, using the `circlize` package.
#### Chord Diagram from Adjacency Matrix
The `chordDiagram()` function of the `circlize` package makes it a breeze to build chord diagrams from adjacency matrix in R.
The adjacency matrix displays all origins in rows, and all destinations in columns. Each cell is filled with a numeric value specifying the flow strength.
<u>Note</u>: Visit the [chord section](https://www.r-graph-gallery.com/chord-diagram.html) of the gallery or the circlize [vignette](https://cran.r-project.org/web/packages/circlize/vignettes/circlize.pdf) for more chord examples.
```r
# Create an adjacency matrix:
# a list of connections between 20 origin nodes, and 5 destination nodes:
numbers <- sample(c(1:1000), 100, replace = T)
data <- matrix( numbers, ncol=5)
rownames(data) <- paste0("orig-", seq(1,20))
colnames(data) <- paste0("dest-", seq(1,5))
# Load the circlize library
library(circlize)
# Make the circular plot
chordDiagram(data, transparency = 0.5)
```
![](https://www.r-graph-gallery.com/123-circular-plot-circlize-package-2_files/figure-html/thecode-1.png)
### Chord Diagram from Edge List
Another common format to store flow information is the edge list. Basically, all connections are stored one by one in a 2 columns file, listing the origin and destination of each.
Since the `chordDiagram()` function expects an adjacency matrix as input, it is required to use the `table()` function for reformating, as described below:
```r
# Create an edge list: a list of connections between 10 origin nodes, and 10 destination nodes:
origin <- paste0("orig ", sample(c(1:10), 20, replace = T))
destination <- paste0("dest ", sample(c(1:10), 20, replace = T))
data <- data.frame(origin, destination)
# Transform input data in a adjacency matrix
adjacencyData <- with(data, table(origin, destination))
# Charge the circlize library
library(circlize)
# Make the circular plot
chordDiagram(adjacencyData, transparency = 0.5)
```
![](https://www.r-graph-gallery.com/123-circular-plot-circlize-package-2_files/figure-html/thecode2-1.png)
The `circlize` package developed by Zuguang Gu is the best way to build chord diagram in R. The [chord diagram](https://www.r-graph-gallery.com/chord-diagram.html) section of the gallery provides a step by step introduction to it.
This example explains how to build a highly customized chord diagram, adding links manually thanks to the `circos.link()` function.
Note that the library also offers a `chordDiagram()` functions that builds everything automatically, but offers less customization. (See it [here](https://www.r-graph-gallery.com/123-circular-plot-circlize-package-2).)
<u>Important</u>: This example has been found on [stackoverflow](http://stackoverflow.com/questions/26292484/programming-in-r-bubble-chart-visualization), made by [Jazzuro](http://stackoverflow.com/users/3304471/jazzurro).
```r
### You need several libraries
library(circlize)
library(migest)
library(dplyr)
### Make data
m <- data.frame(order = 1:6,
country = c("Ausralia", "India", "China", "Japan", "Thailand", "Malaysia"),
V3 = c(1, 150000, 90000, 180000, 15000, 10000),
V4 = c(35000, 1, 10000, 12000, 25000, 8000),
V5 = c(10000, 7000, 1, 40000, 5000, 4000),
V6 = c(7000, 8000, 175000, 1, 11000, 18000),
V7 = c(70000, 30000, 22000, 120000, 1, 40000),
V8 = c(60000, 90000, 110000, 14000, 30000, 1),
r = c(255,255,255,153,51,51),
g = c(51, 153, 255, 255, 255, 255),
b = c(51, 51, 51, 51, 51, 153),
stringsAsFactors = FALSE)
df1 <- m[, c(1,2, 9:11)]
m <- m[,-(1:2)]/1e04
m <- as.matrix(m[,c(1:6)])
dimnames(m) <- list(orig = df1$country, dest = df1$country)
#Sort order of data.frame and matrix for plotting in circos
df1 <- arrange(df1, order)
df1$country <- factor(df1$country, levels = df1$country)
m <- m[levels(df1$country),levels(df1$country)]
### Define ranges of circos sectors and their colors (both of the sectors and the links)
df1$xmin <- 0
df1$xmax <- rowSums(m) + colSums(m)
n <- nrow(df1)
df1$rcol<-rgb(df1$r, df1$g, df1$b, max = 255)
df1$lcol<-rgb(df1$r, df1$g, df1$b, alpha=200, max = 255)
### Plot sectors (outer part)
par(mar=rep(0,4))
circos.clear()
### Basic circos graphic parameters
circos.par(cell.padding=c(0,0,0,0), track.margin=c(0,0.15), start.degree = 90, gap.degree =4)
### Sector details
circos.initialize(factors = df1$country, xlim = cbind(df1$xmin, df1$xmax))
### Plot sectors
circos.trackPlotRegion(ylim = c(0, 1), factors = df1$country, track.height=0.1,
#panel.fun for each sector
panel.fun = function(x, y) {
#select details of current sector
name = get.cell.meta.data("sector.index")
i = get.cell.meta.data("sector.numeric.index")
xlim = get.cell.meta.data("xlim")
ylim = get.cell.meta.data("ylim")
#text direction (dd) and adjusmtents (aa)
theta = circlize(mean(xlim), 1.3)[1, 1] %% 360
dd <- ifelse(theta < 90 || theta > 270, "clockwise", "reverse.clockwise")
aa = c(1, 0.5)
if(theta < 90 || theta > 270) aa = c(0, 0.5)
#plot country labels
circos.text(x=mean(xlim), y=1.7, labels=name, facing = dd, cex=0.6, adj = aa)
#plot main sector
circos.rect(xleft=xlim[1], ybottom=ylim[1], xright=xlim[2], ytop=ylim[2],
col = df1$rcol[i], border=df1$rcol[i])
#blank in part of main sector
circos.rect(xleft=xlim[1], ybottom=ylim[1], xright=xlim[2]-rowSums(m)[i], ytop=ylim[1]+0.3,
col = "white", border = "white")
#white line all the way around
circos.rect(xleft=xlim[1], ybottom=0.3, xright=xlim[2], ytop=0.32, col = "white", border = "white")
#plot axis
circos.axis(labels.cex=0.6, direction = "outside", major.at=seq(from=0,to=floor(df1$xmax)[i],by=5),
minor.ticks=1, labels.away.percentage = 0.15)
})
### Plot links (inner part)
### Add sum values to df1, marking the x-position of the first links
### out (sum1) and in (sum2). Updated for further links in loop below.
df1$sum1 <- colSums(m)
df1$sum2 <- numeric(n)
### Create a data.frame of the flow matrix sorted by flow size, to allow largest flow plotted first
df2 <- cbind(as.data.frame(m),orig=rownames(m), stringsAsFactors=FALSE)
df2 <- reshape(df2, idvar="orig", varying=list(1:n), direction="long",
timevar="dest", time=rownames(m), v.names = "m")
df2 <- arrange(df2,desc(m))
### Keep only the largest flows to avoid clutter
df2 <- subset(df2, m > quantile(m,0.6))
### Plot links
for(k in 1:nrow(df2)){
#i,j reference of flow matrix
i<-match(df2$orig[k],df1$country)
j<-match(df2$dest[k],df1$country)
#plot link
circos.link(sector.index1=df1$country[i], point1=c(df1$sum1[i], df1$sum1[i] + abs(m[i, j])),
sector.index2=df1$country[j], point2=c(df1$sum2[j], df1$sum2[j] + abs(m[i, j])),
col = df1$lcol[i])
#update sum1 and sum2 for use when plotting the next link
df1$sum1[i] = df1$sum1[i] + abs(m[i, j])
df1$sum2[j] = df1$sum2[j] + abs(m[i, j])
}
```
![](https://www.r-graph-gallery.com/122-a-circular-plot-with-the-circlize-package_files/figure-html/thecode-1.png)
### Chord Diagram
A [chord diagram](https://www.data-to-viz.com/graph/chord.html) represents flows or connections between several entities (called nodes). Each entity is represented by a fragment on the outer part of the circular layout. Then, arcs are drawn between each entities. The size of the arc is proportional to the importance of the flow.
Here is an example displaying the number of people migrating from one country to another. Data used comes from this scientific publication from Gui J. Abel.
```r
# Libraries
library(tidyverse)
library(viridis)
library(patchwork)
library(hrbrthemes)
library(circlize)
library(chorddiag) #devtools::install_github("mattflor/chorddiag")
# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/13_AdjacencyDirectedWeighted.csv", header=TRUE)
# short names
colnames(data) <- c("Africa", "East Asia", "Europe", "Latin Ame.", "North Ame.", "Oceania", "South Asia", "South East Asia", "Soviet Union", "West.Asia")
rownames(data) <- colnames(data)
# I need a long format
data_long <- data %>%
rownames_to_column %>%
gather(key = 'key', value = 'value', -rowname)
# parameters
circos.clear()
circos.par(start.degree = 90, gap.degree = 4, track.margin = c(-0.1, 0.1), points.overflow.warning = FALSE)
par(mar = rep(0, 4))
# color palette
mycolor <- viridis(10, alpha = 1, begin = 0, end = 1, option = "D")
mycolor <- mycolor[sample(1:10)]
# Base plot
chordDiagram(
x = data_long,
grid.col = mycolor,
transparency = 0.25,
directional = 1,
direction.type = c("arrows", "diffHeight"),
diffHeight = -0.04,
annotationTrack = "grid",
annotationTrackHeight = c(0.05, 0.1),
link.arr.type = "big.arrow",
link.sort = TRUE,
link.largest.ontop = TRUE)
# Add text and axis
circos.trackPlotRegion(
track.index = 1,
bg.border = NA,
panel.fun = function(x, y) {
xlim = get.cell.meta.data("xlim")
sector.index = get.cell.meta.data("sector.index")
# Add names to the sector.
circos.text(
x = mean(xlim),
y = 3.2,
labels = sector.index,
facing = "bending",
cex = 0.8
)
# Add graduation on axis
circos.axis(
h = "top",
major.at = seq(from = 0, to = xlim[2], by = ifelse(test = xlim[2]>10, yes = 2, no = 1)),
minor.ticks = 1,
major.tick.percentage = 0.5,
labels.niceFacing = FALSE)
}
)
```
![](https://www.data-to-viz.com/graph/chord_files/figure-html/unnamed-chunk-1-1.png)
### Variations
Interactivity is a real plus to make the chord diagram understandable. In the example below, you can hover a specific group to highlight all its connections.
```{r chord-diagram-variations-interactive, echo=TRUE, message=FALSE, warning=FALSE}
library(chorddiag)
m <- matrix(c(11975, 5871, 8916, 2868,
1951, 10048, 2060, 6171,
8010, 16145, 8090, 8045,
1013, 990, 940, 6907),
byrow = TRUE,
nrow = 4, ncol = 4)
haircolors <- c("black", "blonde", "brown", "red")
dimnames(m) <- list(have = haircolors,
prefer = haircolors)
groupColors <- c("#000000", "#FFDD89", "#957244", "#F26223")
chorddiag(m, groupColors = groupColors, groupnamePadding = 20)
```
### Static Chord Diagram
The `circlize` package also offers functions to build chord diagrams. Basically, it allows to add arcs between nodes to show flows. The examples below will guide you through their usage. The `circos.links()` function builds connection one by one, when `chordDiagram()` plot a whole dataset in one shot.
### Introduction to Chord Diagram
The `circlize` package allows to build [chord diagrams](https://www.r-graph-gallery.com/chord-diagram.html), where arcs between sections are built to show flows.
Chart [#224](https://www.r-graph-gallery.com/224-basic-circular-plot.html), and [#225](https://www.r-graph-gallery.com/225-circular-plot-custom-a-track.html) introduced the `circlize` package and its ability to build circular charts.
It is possible to add connections between tracks with `circos.links()`.
See [chart #122](https://www.r-graph-gallery.com/122-a-circular-plot-with-the-circlize-package.html) for a customized version, and [chart #123](https://www.r-graph-gallery.com/123-circular-plot-circlize-package-2.html) for an automatized version.
```{r intro-chord-diagrams, echo=TRUE, warning=FALSE, message=FALSE}
# library
library(circlize)
# Create data
set.seed(123)
data = data.frame(
factor = sample(letters[1:8], 1000, replace = TRUE),
x = rnorm(1000),
y = runif(1000)
)
# Initialize the plot.
par(mar = c(1, 1, 1, 1) )
circos.initialize(factors = data$factor, x = data$x )
# Build the regions of track #1
circos.trackPlotRegion(factors = data$factor, y=data$y , bg.col = rgb(0.1,0.1,seq(0,1,0.1),0.4) , bg.border = NA)
# Add a link between a point and another
circos.link("a", 0, "b", 0, h = 0.4)
# Add a link between a point and a zone
circos.link("e", 0, "g", c(-1,1), col = "green", lwd = 2, lty = 2, border="black" )
# Add a link between a zone and another
circos.link("c", c(-0.5, 0.5), "d", c(-0.5,0.5), col = "red", border = "blue", h = 0.2)
```
### Chord Diagram from Adjacency Matrix
The `circlize` package developped by [Zuguang Gu](https://github.com/jokergoo) is the best way to build [chord diagram](https://www.r-graph-gallery.com/chord-diagram.html) in R. The chord diagram section of the gallery provides a step by step introduction to it.
This example explains how to build a highly customized chord diagram, adding links manually thanks to the `circos.link()` function.
Note that the library also offers a `chordDiagram()` functions that builds everything automatically, but offers less customization. (See it [here](https://www.r-graph-gallery.com/123-circular-plot-circlize-package-2).)
Important: This example has been found on [stackoverflow](http://stackoverflow.com/questions/26292484/programming-in-r-bubble-chart-visualization), made by [Jazzuro](http://stackoverflow.com/users/3304471/jazzurro).
```r
### You need several libraries
library(circlize)
library(migest)
library(dplyr)
### Make data
m <- data.frame(order = 1:6,
country = c("Ausralia", "India", "China", "Japan", "Thailand", "Malaysia"),
V3 = c(1, 150000, 90000, 180000, 15000, 10000),
V4 = c(35000, 1, 10000, 12000, 25000, 8000),
V5 = c(10000, 7000, 1, 40000, 5000, 4000),
V6 = c(7000, 8000, 175000, 1, 11000, 18000),
V7 = c(70000, 30000, 22000, 120000, 1, 40000),
V8 = c(60000, 90000, 110000, 14000, 30000, 1),
r = c(255,255,255,153,51,51),
g = c(51, 153, 255, 255, 255, 255),
b = c(51, 51, 51, 51, 51, 153),
stringsAsFactors = FALSE)
df1 <- m[, c(1,2, 9:11)]
m <- m[,-(1:2)]/1e04
m <- as.matrix(m[,c(1:6)])
dimnames(m) <- list(orig = df1$country, dest = df1$country)
#Sort order of data.frame and matrix for plotting in circos
df1 <- arrange(df1, order)
df1$country <- factor(df1$country, levels = df1$country)
m <- m[levels(df1$country),levels(df1$country)]
### Define ranges of circos sectors and their colors (both of the sectors and the links)
df1$xmin <- 0
df1$xmax <- rowSums(m) + colSums(m)
n <- nrow(df1)
df1$rcol<-rgb(df1$r, df1$g, df1$b, max = 255)
df1$lcol<-rgb(df1$r, df1$g, df1$b, alpha=200, max = 255)
### Plot sectors (outer part)
par(mar=rep(0,4))
circos.clear()
### Basic circos graphic parameters
circos.par(cell.padding=c(0,0,0,0), track.margin=c(0,0.15), start.degree = 90, gap.degree =4)
### Sector details
circos.initialize(factors = df1$country, xlim = cbind(df1$xmin, df1$xmax))
### Plot sectors
circos.trackPlotRegion(ylim = c(0, 1), factors = df1$country, track.height=0.1,
#panel.fun for each sector
panel.fun = function(x, y) {
#select details of current sector
name = get.cell.meta.data("sector.index")
i = get.cell.meta.data("sector.numeric.index")
xlim = get.cell.meta.data("xlim")
ylim = get.cell.meta.data("ylim")
#text direction (dd) and adjusmtents (aa)
theta = circlize(mean(xlim), 1.3)[1, 1] %% 360
dd <- ifelse(theta < 90 || theta > 270, "clockwise", "reverse.clockwise")
aa = c(1, 0.5)
if(theta < 90 || theta > 270) aa = c(0, 0.5)
#plot country labels
circos.text(x=mean(xlim), y=1.7, labels=name, facing = dd, cex=0.6, adj = aa)
#plot main sector
circos.rect(xleft=xlim[1], ybottom=ylim[1], xright=xlim[2], ytop=ylim[2],
col = df1$rcol[i], border=df1$rcol[i])
#blank in part of main sector
circos.rect(xleft=xlim[1], ybottom=ylim[1], xright=xlim[2]-rowSums(m)[i], ytop=ylim[1]+0.3,
col = "white", border = "white")
#white line all the way around
circos.rect(xleft=xlim[1], ybottom=0.3, xright=xlim[2], ytop=0.32, col = "white", border = "white")
#plot axis
circos.axis(labels.cex=0.6, direction = "outside", major.at=seq(from=0,to=floor(df1$xmax)[i],by=5),
minor.ticks=1, labels.away.percentage = 0.15)
})
### Plot links (inner part)
### Add sum values to df1, marking the x-position of the first links
### out (sum1) and in (sum2). Updated for further links in loop below.
df1$sum1 <- colSums(m)
df1$sum2 <- numeric(n)
### Create a data.frame of the flow matrix sorted by flow size, to allow largest flow plotted first
df2 <- cbind(as.data.frame(m),orig=rownames(m), stringsAsFactors=FALSE)
df2 <- reshape(df2, idvar="orig", varying=list(1:n), direction="long",
timevar="dest", time=rownames(m), v.names = "m")
df2 <- arrange(df2,desc(m))
### Keep only the largest flows to avoid clutter
df2 <- subset(df2, m > quantile(m,0.6))
### Plot links
for(k in 1:nrow(df2)){
#i,j reference of flow matrix
i<-match(df2$orig[k],df1$country)
j<-match(df2$dest[k],df1$country)
#plot link
circos.link(sector.index1=df1$country[i], point1=c(df1$sum1[i], df1$sum1[i] + abs(m[i, j])),
sector.index2=df1$country[j], point2=c(df1$sum2[j], df1$sum2[j] + abs(m[i, j])),
col = df1$lcol[i])
#update sum1 and sum2 for use when plotting the next link
df1$sum1[i] = df1$sum1[i] + abs(m[i, j])
df1$sum2[j] = df1$sum2[j] + abs(m[i, j])
}
```
<center>
![](https://www.r-graph-gallery.com/123-circular-plot-circlize-package-2_files/figure-html/thecode-1.png){width=75%}
</center>
## Edge Bundling
---
### Hierarchical Edge Bundling
[Hierarchical edge bundling](https://www.data-to-viz.com/graph/edge_bundling.html) allows to visualize <u>adjacency relations</u> between entities organized in a <u>hierarchy</u>. The idea is to <u>bundle</u> the adjacency edges together to <u>decrease the clutter</u> usually observed in complex networks. The `ggraph` package is the best tool to build this kind of chart in R.
#### What is Hierarchical Edge Bundling?
The following post will guide you through the basics of hierarchical edge bundling. It explains what this kind of chart really is, describing step by step how to build it in `R` with the `graph` package.
### Introduction to Hierarchical Edge Bundling with R
This section defines what [hierarchical edge bundling](https://www.r-graph-gallery.com/hierarchical-edge-bundling.html) is. It provides a basic implementation using `R` and the `ggraph` library. For an in depth explanation, visit [data-to-viz.com](https://www.data-to-viz.com/caveat/overplotting.html).
#### Input Data
[Hierarchical Edge Bundling](https://www.r-graph-gallery.com/hierarchical-edge-bundling.html) is a data visualisation method allowing to check connections between leaves of a hierarchical network. It requires two inputs:
* A hierarchical network structure, also called tree.
* An adjacency matrix that describes connections between some nodes of the tree.