├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── pkgdown.yaml │ └── test-coverage.yaml ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS ├── NEWS.md ├── R ├── genes.R ├── ggparallel.R └── help.R ├── README.Rmd ├── README.md ├── README_files ├── figure-html │ ├── unnamed-chunk-1-1.png │ └── unnamed-chunk-1-2.png └── figure-markdown_strict │ ├── unnamed-chunk-1-1.png │ └── unnamed-chunk-1-2.png ├── _pkgdown.yml ├── codecov.yml ├── cran-comments.md ├── data ├── .DS_Store └── genes.rda ├── docs ├── 404.html ├── LICENSE-text.html ├── authors.html ├── bootstrap-toc.css ├── bootstrap-toc.js ├── docsearch.css ├── docsearch.js ├── index.html ├── link.svg ├── news │ └── index.html ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── reference │ ├── Rplot001.png │ ├── Rplot002.png │ ├── Rplot003.png │ ├── Rplot004.png │ ├── Rplot005.png │ ├── Rplot006.png │ ├── Rplot007.png │ ├── Rplot008.png │ ├── Rplot009.png │ ├── Rplot010.png │ ├── figures │ │ ├── README-unnamed-chunk-2-1.png │ │ └── README-unnamed-chunk-3-1.png │ ├── genes-1.png │ ├── genes.html │ ├── ggparallel-1.png │ ├── ggparallel-10.png │ ├── ggparallel-2.png │ ├── ggparallel-3.png │ ├── ggparallel-4.png │ ├── ggparallel-5.png │ ├── ggparallel-6.png │ ├── ggparallel-7.png │ ├── ggparallel-8.png │ ├── ggparallel-9.png │ ├── ggparallel.html │ ├── index.html │ └── package-ggparallel.html └── sitemap.xml ├── ggparallel.Rproj ├── inst ├── CITATION ├── examples │ └── ggparallel-ex.R ├── mtcars.rda ├── references.bib ├── titanic_adjangle.rda └── titanic_hammock.rda ├── man ├── figures │ ├── README-unnamed-chunk-2-1.png │ └── README-unnamed-chunk-3-1.png ├── genes.Rd ├── ggparallel.Rd └── package-ggparallel.Rd └── tests ├── testthat.R └── testthat └── test-ggparallel.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^cran-comments\.md$ 4 | ^README\.md$ 5 | ^README.*$ 6 | ^visual_test$ 7 | ^visual_test_outdated$ 8 | ^\.travis\.yml$ 9 | ^README\.Rmd$ 10 | ^codecov\.yml$ 11 | ^\.github$ 12 | docs 13 | ^_pkgdown\.yml$ 14 | ^docs$ 15 | ^pkgdown$ 16 | ^CRAN-SUBMISSION$ 17 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 51 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | permissions: 23 | contents: write 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - uses: r-lib/actions/setup-pandoc@v2 28 | 29 | - uses: r-lib/actions/setup-r@v2 30 | with: 31 | use-public-rspm: true 32 | 33 | - uses: r-lib/actions/setup-r-dependencies@v2 34 | with: 35 | extra-packages: any::pkgdown, local::. 36 | needs: website 37 | 38 | - name: Build site 39 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 40 | shell: Rscript {0} 41 | 42 | - name: Deploy to GitHub pages 🚀 43 | if: github.event_name != 'pull_request' 44 | uses: JamesIves/github-pages-deploy-action@v4.5.0 45 | with: 46 | clean: false 47 | branch: gh-pages 48 | folder: docs 49 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::covr 27 | needs: coverage 28 | 29 | - name: Test coverage 30 | run: | 31 | covr::codecov( 32 | quiet = FALSE, 33 | clean = FALSE, 34 | install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package") 35 | ) 36 | shell: Rscript {0} 37 | 38 | - name: Show testthat output 39 | if: always() 40 | run: | 41 | ## -------------------------------------------------------------------- 42 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 43 | shell: bash 44 | 45 | - name: Upload test results 46 | if: failure() 47 | uses: actions/upload-artifact@v4 48 | with: 49 | name: coverage-test-failures 50 | path: ${{ runner.temp }}/package 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | docs 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | r: 5 | - oldrel 6 | - release 7 | - devel 8 | sudo: false 9 | cache: packages 10 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ggparallel 2 | Version: 0.4.0 3 | Date: 2024-03-09 4 | Title: Variations of Parallel Coordinate Plots for Categorical Data 5 | Authors@R: c( 6 | person("Heike", "Hofmann", , "hofmann@mail.iastate.edu",c("aut", "cre"), 7 | comment = c(ORCID = "0000-0001-6216-5183")), 8 | person("Marie","Vendettuoli", role="aut") 9 | ) 10 | Description: Create hammock plots, parallel sets, and common angle plots 11 | with 'ggplot2'. 12 | License: MIT + file LICENSE 13 | Depends: 14 | R (>= 3.5.0), 15 | ggplot2 (>= 3.5.0) 16 | Imports: 17 | reshape2 (>= 1.4.4), 18 | plyr (>= 1.8.9) 19 | Suggests: 20 | RColorBrewer, 21 | testthat (>= 3.0.0) 22 | URL: https://github.com/heike/ggparallel/, https://heike.github.io/ggparallel/ 23 | BugReports: https://github.com/heike/ggparallel/issues/ 24 | LazyData: true 25 | RoxygenNote: 7.2.3 26 | Encoding: UTF-8 27 | Config/testthat/edition: 3 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2012-2024 2 | COPYRIGHT HOLDER: Heike Hofmann; Marie Vendettuoli 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(ggparallel) 4 | import(ggplot2) 5 | import(plyr) 6 | import(reshape2) 7 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | Changes across different versions 3 | ============================================================ 4 | ------------------------------------------------------------ 5 | Version 0.1.1 6 | ------------------------------------------------------------ 7 | * new feature: added method 'adj.angle' 8 | * renamed parameter angle to text.angle 9 | * removed colour from outline of common angle ribbons 10 | * bug fix: order of variables considered in drawing ribbons for hammock plots 11 | ------------------------------------------------------------ 12 | Version 0.1.2 13 | ------------------------------------------------------------ 14 | * removed the Rproj file from the package 15 | * added parameter label.size 16 | ------------------------------------------------------------ 17 | Version 0.2.0 18 | ------------------------------------------------------------ 19 | * adjusted order of categories to new ggplot2 filling order in barcharts 20 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # ggparallel 0.4.0 2 | 3 | - Fix to test data. 4 | 5 | # ggparallel 0.3.0 6 | 7 | - Required change to package documentation. 8 | 9 | 10 | # ggparallel 0.2.0 11 | 12 | - Added a `NEWS.md` file to track changes to the package. 13 | -------------------------------------------------------------------------------- /R/genes.R: -------------------------------------------------------------------------------- 1 | #' Data linking genes and pathways. 2 | #' 3 | #' Table knownGene from track UCSC Genes was downloaded from the UCSC table 4 | #' browser for the human genome assembly (hg18, May 2006) and filtered for a 5 | #' selection of pathways associated with human metabolism was obtained from KEGG 6 | #' PATHWAY database. Bioconductor package KEGG.db was used to provide mappings 7 | #' between gene and pathway identifiers. 8 | #' 9 | #' @references Fujita PA, Rhead B, Zweig AS, Hinrichs AS, Karolchik D, Cline MS, 10 | #' Goldman M, Barber GP, Clawson H, Coelho A, Diekhans M, Dreszer TR, Giardine 11 | #' BM, Harte RA, Hillman-Jackson J, Hsu F, Kirkup V, Kuhn RM, Learned K, Li CH, 12 | #' Meyer LR, Pohl A, Raney BJ, Rosenbloom KR, Smith KE, Haussler D, Kent WJ. The 13 | #' UCSC Genome Browser database: update 2011. Nucleic Acids Res. 2010 Oct 18. 14 | #' \url{http://genome.ucsc.edu/index.html?org=Human&db=hg19&hgsid=289810087} 15 | #' 16 | #' Marc Carlson, Seth Falcon, Herve Pages and Nianhua Li (). KEGG.db: A set 17 | #' of annotation maps for KEGG. R package version 2.6.1. 18 | #' 19 | #' Kanehisa, M., Goto, S., Sato, Y., Furumichi, M., and Tanabe, M.; KEGG for 20 | #' integration and interpretation of large-scale molecular datasets. Nucleic 21 | #' Acids Res. 40, D109-D114 (2012) 22 | #' 23 | #' Kanehisa, M. and Goto, S.; KEGG: Kyoto Encyclopedia of Genes and Genomes. 24 | #' Nucleic Acids Res. 28, 27-30 (2000). 25 | #' @examples 26 | #' library(ggplot2) 27 | #' library(RColorBrewer) 28 | #' genes$chrom <- factor(genes$chrom, levels=c(paste("chr", 1:22, sep=""), 29 | #' "chrX", "chrY")) 30 | #' ggparallel( 31 | #' list("path", "chrom"), 32 | #' text.offset = c(0.03, 0,-0.03), 33 | #' data = genes, 34 | #' width = 0.1, 35 | #' order = c(1, 0), 36 | #' angle = 0, 37 | #' color = "white", 38 | #' factorlevels = c(sapply(unique(genes$chrom), as.character),unique(genes$path)) 39 | #' ) + 40 | #' scale_fill_manual( 41 | #' values = c(brewer.pal("YlOrRd", n = 9), rep("grey80", 24)), 42 | #' guide = "none" 43 | #' ) + 44 | #' scale_colour_manual( 45 | #' values = c(brewer.pal("YlOrRd", n = 9), rep("grey80", 24)), 46 | #' guide = "none" 47 | #' ) + 48 | #' coord_flip() 49 | "genes" 50 | -------------------------------------------------------------------------------- /R/ggparallel.R: -------------------------------------------------------------------------------- 1 | #' Variations of parallel coordinate plots 2 | #' 3 | #' \code{\link{ggparallel}} implements and combines different types of parallel 4 | #' coordinate plots for categorical data: hammock plots, parallel sets plots, 5 | #' common angle plots, and common angle plots with a hammock-like adjustment 6 | #' for line widths. 7 | #' 8 | #' Parallel sets have been suggested by \cite{kosara:2006} as a visualization 9 | #' technique to incorporate categorical variables into a parallel coordinate 10 | #' plot introduced by \cite{wegman:1990} and \cite{inselberg:1985}. The parallel 11 | #' sets implemented here are reduced to representations of neighboring 12 | #' two-dimensional relationships only rather than the hierarchical version 13 | #' originally suggested. 14 | #' 15 | #' Both versions, however, show perceptual problems with interpreting line 16 | #' widths, leading to potentially wrong conclusions about the data. The hammock 17 | #' display, introduced by \cite{schonlau:2003}, and the common angle plots are 18 | #' two approaches at fixing this problem: in Hammock plots the linewidth is 19 | #' adjusted by a factor countering the strength of the illusion, in the common 20 | #' angle plot all lines are adjusted to show the same angle - making line widths 21 | #' again comparable across ribbons. 22 | #' 23 | #' Additionally, we can also adjust ribbons in the common angle display for the 24 | #' angle, to make them appear having the same width (or height) across the 25 | #' display. We refer to this method as \code{adj.angle}. 26 | #' 27 | #' @param vars list of variable names to be included in the plotting. Order of 28 | #' the variables is preserved in the display 29 | #' @param data data frame 30 | #' @param weight weighting variable - use character string 31 | #' @param method plotting method to use - one of \code{angle}, 32 | #' \code{adj.angle}, \code{parset}, or \code{hammock}, for a hammock plot 33 | #' the aspect ratio needs to be fixed. 34 | #' @param alpha level of alpha blending for the fill color in ribbons, value 35 | #' has to be between 0 and 1, defaults to 0.5. 36 | #' @param width width of variables 37 | #' @param order flag variable with three levels -1, 0, 1 for levels in 38 | #' decreasing order, levels in increasing order and levels unchanged. This 39 | #' variable can be either a scalar or a vector 40 | #' @param ratio used for methods with angle adjustments (method = 41 | #' \code{'hammock', 'adj.angle'}): specifies the height (width for horizontal 42 | #' displays) of the widest line as ratio of the overall display height (width 43 | #' for horizontal displays). 44 | #' @param label binary variable (vector), whether labels should be shown. 45 | #' @param label.size numeric value to determine the size in which labels are shown, defaults to 4 46 | #' @param label.colour character of colour in which the label should be shown. Ignored, if `label` is FALSE. 47 | #' @param text.angle numeric value to determine the angle under which labels are shown. 48 | #' @param text.offset (vector) of values for offsetting the labels 49 | #' @param asp aspect ratio of the plot - it will be set to a default of 1 in 50 | #' the case of hammock plots. 51 | #' @param same.level are all variables using the same levels? If yes, simplify the labelling 52 | #' @param ... passed on directly to all of the ggplot2 commands 53 | #' @return returns a ggplot2 object that can be plotted directly or used as base 54 | #' layer for additional modifications. 55 | #' @export 56 | #' @import ggplot2 plyr reshape2 57 | #' @example inst/examples/ggparallel-ex.R 58 | ggparallel <- function(vars=list(), data, weight=NULL, method="angle", 59 | alpha=0.5, width = 0.25, order = 1, ratio=NULL, 60 | asp = NULL, label = TRUE, label.colour="grey90", label.size=4, text.angle=90, 61 | text.offset=NULL, same.level=FALSE, ...) { 62 | ### error checking 63 | vars <- unlist(vars) 64 | k = length(vars) 65 | if (k < 2) message("Error: ggparallel needs at least two variables. Use vars=list('X', 'Y')") 66 | 67 | ## if user doesn't specify the weight, assign value of 1. 68 | data$weight <- weight 69 | if (is.null(weight)) data$weight <- 1 70 | if (is.character(weight)) data$weight <- data[,weight] 71 | if (is.null(ratio)) ratio <- nrow(data)/sum(data$weight) 72 | 73 | ## if ordering is selected, organize x and y axis by weight 74 | ## make order a vector of length length(vars) 75 | order <- rep(order, length=length(vars)) 76 | for (i in 1:length(vars)){ 77 | if (! is.factor(data[,vars[i]])) 78 | data[,vars[i]] <- factor(data[,vars[i]]) 79 | 80 | if (order[i] != 0) 81 | data[,vars[i]] <- stats::reorder(data[,vars[i]], data$weight, 82 | function(x) if (order[i] > 0) sum(x) 83 | else -sum(x) 84 | ) 85 | } 86 | 87 | llist <- NULL 88 | for (i in unique(vars)) { 89 | if (!same.level) levels(data[,i]) <- paste(i, levels(data[,i]), sep=":") 90 | llist <- c(llist, levels(data[,i])) 91 | } 92 | if ((method=="hammock"))# | (method=="adj.angle")) 93 | if (is.null(asp)) asp <- 1 94 | 95 | ## helper function 96 | getRibbons <- function(xid,yid) { 97 | ## get the names of the x and y variables 98 | x <- vars[xid] 99 | y <- vars[yid] 100 | 101 | xname <- x 102 | yname <- y 103 | 104 | ## introduce new variables as fail-safe, if local binding fails: 105 | variable <- NULL 106 | value <- NULL 107 | Freq <- NULL 108 | Nodeset <- NULL 109 | tangens <- NULL 110 | dx2 <- NULL 111 | midx <- NULL 112 | midy <- NULL 113 | ypos <- NULL 114 | varn <- NULL 115 | ymax <- NULL 116 | ymin <- NULL 117 | ymid <- NULL 118 | xoffset <- NULL 119 | 120 | ## create the data table, x, y, and weight 121 | dfxy <- as.data.frame(stats::xtabs(data$weight~data[,x] + data[,y])) 122 | dfxy <- subset(dfxy, Freq > 0) 123 | 124 | names(dfxy)[1:2] <- c(xname, yname) 125 | 126 | ## get the ordering for data according to x-axis categories 127 | idx <- order(dfxy[,x], dfxy[,y], decreasing = TRUE) 128 | 129 | ## find the position of X-axis connector 130 | dfxy$X[idx] <- sum(dfxy$Freq[idx]) - cumsum(dfxy$Freq[idx]) 131 | dfxy$X[idx] <- dfxy$X[idx] + dfxy$Freq[idx] 132 | 133 | ## get the ordering for data according to y-axis categories 134 | idx <- order(dfxy[,y], dfxy[,x], decreasing = TRUE) 135 | 136 | ## find the position of the Y-axis connector 137 | dfxy$Y[idx] <- sum(dfxy$Freq[idx]) - cumsum(dfxy$Freq[idx]) 138 | dfxy$Y[idx] <- dfxy$Y[idx] + dfxy$Freq[idx] 139 | 140 | ## assign row number as id 141 | dfxy$id <- 1:nrow(dfxy) 142 | dfm <- melt(dfxy, measure.var=c("X", "Y")) 143 | levels(dfm$variable) <- c(x,y) 144 | 145 | dfxy$XX <- dfxy[,xname] 146 | dfxy$YY <- dfxy[,yname] 147 | dfm$Nodeset <- dfm[,xname] 148 | dfm$Nodeset <- factor(dfm$Nodeset, levels=llist) 149 | 150 | dfm$xoffset <- c(width/2,-width/2)[as.numeric(dfm$variable)] 151 | dfm$xid <- xid - 1 152 | dfm$yid <- yid 153 | 154 | if (method=="parset") { 155 | r <- geom_ribbon(aes(x=as.numeric(variable)+xoffset+xid, 156 | ymin=value-Freq, 157 | ymax= value, group=id, 158 | fill=Nodeset, colour=Nodeset), alpha=alpha, data=dfm) 159 | } 160 | if (method == "angle") { 161 | dfm$x <- with(dfm, as.numeric(variable)+xoffset+xid) 162 | dfm<- ddply(dfm, .(id), transform, 163 | dx=max(x)-min(x), 164 | dy=max(value) -min(value) 165 | ) 166 | dfm$tangens = dfm$dy/dfm$dx 167 | maxslope <- 1.3*max(dfm$tangens) # add 15% of offset on each end of each variable 168 | dfm$newdx <- with(dfm, dy/maxslope) 169 | 170 | dfm2 <- dfm 171 | dfm2$xoffset <- with(dfm, (abs(xoffset) + (dx-newdx)/2) * sign(xoffset)) 172 | dfm2$x <- with(dfm2, as.numeric(variable)+xoffset+xid) 173 | dfm3 <- ddply(dfm2, names(dfm2)[2], transform, 174 | dx2 = max(x[which(tangens==max(tangens))]) 175 | ) 176 | dfm3 <- ddply(dfm3, .(id), transform, shiftx = max(x)-dx2) 177 | dfm3$x <- dfm3$x - dfm3$shiftx 178 | dfm <- rbind(dfm, dfm3[,-(16:17)]) 179 | r <- geom_ribbon(aes(x=x,ymin=value -Freq, ymax= value, group=id, 180 | fill=Nodeset, colour=Nodeset), alpha=alpha, data=dfm) 181 | } 182 | if (method == "adj.angle") { 183 | dfm$x <- with(dfm, as.numeric(variable)+xoffset+xid) 184 | dfm<- ddply(dfm, .(id), transform, 185 | dx=max(x)-min(x), 186 | dy=max(value) -min(value) 187 | ) 188 | dfm$tangens = dfm$dy/dfm$dx 189 | maxslope <- 1.3*max(dfm$tangens) # add 15% of offset on each end of each variable 190 | dfm$newdx <- with(dfm, dy/maxslope) 191 | 192 | dfm2 <- dfm 193 | dfm2$xoffset <- with(dfm, (abs(xoffset) + (dx-newdx)/2) * sign(xoffset)) 194 | dfm2$x <- with(dfm2, as.numeric(variable)+xoffset+xid) 195 | dfm3 <- ddply(dfm2, names(dfm2)[2], transform, 196 | dx2 = max(x[which(tangens==max(tangens))]) 197 | ) 198 | dfm3 <- ddply(dfm3, .(id), transform, shiftx = max(x)-dx2) 199 | dfm3$x <- dfm3$x #- dfm3$shiftx 200 | dfm <- rbind(dfm, dfm3[,-(16:17)]) 201 | dfm <- transform(dfm, ymin=value-Freq, ymax=value) 202 | dfm <- transform(dfm, ymid=(ymax+ymin)/2) 203 | # plot.asp <- length(vars)/(1.1*sum(data$weight))*asp 204 | # qplot(x, ymid, data=dfm, geom=c("line"), alpha=I(0.5), group=id, colour=factor(gear), size=Freq)+scale_size(range=4.2*c(min(dfm$Freq),max(dfm$Freq))) + scale_colour_discrete() + theme(legend.position="none") + ylim(c(0, 1.05*sum(data$weight))) 205 | #browser() 206 | r <- list(geom_line( 207 | aes(x=x,y=ymid, group=id, colour=Nodeset, linewidth=Freq), 208 | alpha=alpha, data=dfm), range=c(min(dfm$Freq),max(dfm$Freq))) 209 | # r <- list(geom_line(aes(x=x,y=ymid, group=id, colour=Nodeset, size=Freq), alpha=alpha, data=dfm), 210 | # scale_size(guide="none", range=ratio*max(dfm$Freq)*c(min(dfm$Freq),max(dfm$Freq)))) #+ scale_colour_discrete() 211 | } 212 | if (method=="hammock") { 213 | maxwidth = ratio/2*sum(data$weight) 214 | xtab <- ddply(dfxy, xname, summarise, value=sum(Freq)) 215 | xtab$midx <- with(xtab, cumsum(value)- value/2) 216 | dfm <- merge(dfm, xtab[,c(xname, "midx")], by=xname) 217 | ytab <- ddply(dfxy, yname, summarise, value=sum(Freq)) 218 | ytab$midy <- with(ytab, cumsum(value)- value/2) 219 | dfm <- merge(dfm, ytab[,c(yname, "midy")], by=yname) 220 | plot.asp <- length(vars)/(1.1*sum(data$weight))*asp 221 | 222 | dfm$varn <- as.numeric(dfm$variable) 223 | dfm <- transform(dfm, 224 | x = min(varn+xoffset+xid), 225 | xend = max(varn+xoffset+xid) 226 | ) 227 | dfm <- ddply(dfm , .(id), transform, 228 | tangens = max(midy)-min(midx) 229 | ) 230 | dfm$tangens <- with(dfm, tangens/max(xend-x)*plot.asp) 231 | dfm$width <- with(dfm, Freq/cos(atan(tangens))) 232 | dfm$width <- with(dfm, width*maxwidth/max(width)) 233 | dfm <- ddply(dfm, .(id), transform, 234 | y=c(midx[1], midy[1])[varn] 235 | ) 236 | 237 | r <- geom_ribbon(aes(x=as.numeric(variable)+xoffset+xid, 238 | ymin=y-width, ymax=y+width, group=id, 239 | fill=Nodeset, colour=Nodeset), alpha=alpha, data=dfm) #, drop=FALSE) 240 | } 241 | r 242 | } 243 | ## end helper function 244 | 245 | ## local variables 246 | variable <- NULL 247 | Freq <- NULL 248 | Nodeset <- NULL 249 | ypos <- NULL 250 | 251 | gr <- list() 252 | for (i in 1:(length(vars)-1)) 253 | gr[[i]] <- getRibbons(i,i+1) 254 | 255 | if (method=="adj.angle") { 256 | prange <- c(NA,NA) 257 | for (i in 1:(length(vars)-1)) { 258 | prange <- range(c(prange, gr[[i]][[2]]), na.rm=T) 259 | gr[[i]] <- gr[[i]][[1]] 260 | } 261 | gr[[1]] <- list(gr[[1]], scale_size(guide="none", range=ratio*prange)) 262 | } 263 | 264 | subdata <- data[,c("weight", unlist(vars))] 265 | for (i in unlist(vars)) subdata[,i] <- as.character(subdata[,i]) 266 | dfm <- melt(subdata, id.var="weight") 267 | names(dfm)[3] <- "Nodeset" 268 | dfm$Nodeset <- factor(dfm$Nodeset, levels=llist) 269 | 270 | llabels <- NULL 271 | if (label) { 272 | label.stats <- ddply(dfm, .(variable, Nodeset), summarize, 273 | n = length(weight), 274 | weight=sum(weight) 275 | ) 276 | maxWeight <- sum(label.stats$weight)/length(unique(label.stats$variable)) 277 | label.stats$ypos <- cumsum(label.stats$weight)-(as.numeric(label.stats$variable)-1)*maxWeight 278 | label.stats$ypos <- label.stats$ypos-label.stats$weight/2 279 | 280 | if (is.null(text.offset)) text.offset <- 0 281 | label.stats$text.offset <- rep(text.offset, length=nrow(label.stats)) 282 | 283 | varnames <- paste(unlist(vars), sep="|", collapse="|") 284 | label.stats$labels <- gsub(sprintf("(%s):(.*)",varnames),"\\2", as.character(label.stats$Nodeset)) 285 | llabels <- list(#geom_text(aes(x=as.numeric(variable)+text.offset, y=ypos, label=labels), 286 | # colour = "grey20", data=label.stats, angle=text.angle, size=label.size), 287 | geom_text(aes(x=as.numeric(variable)+0.01+text.offset, y=ypos-0.01, label=labels), 288 | colour = label.colour, data=label.stats, angle=text.angle, size=label.size)) 289 | } 290 | theme.layer <- NULL 291 | if (!is.null(asp)) theme.layer <- theme(aspect.ratio=asp) 292 | dfm$Nodeset <- factor(dfm$Nodeset, levels = rev(levels(dfm$Nodeset))) 293 | ggplot() + xlab("") + gr + theme.layer + 294 | geom_bar(aes(weight=weight, x=variable, fill=Nodeset, colour=Nodeset), width=width, data=dfm) + 295 | llabels + 296 | scale_x_discrete(expand=c(0.1, 0.1)) 297 | # theme(drop=FALSE) 298 | } 299 | 300 | -------------------------------------------------------------------------------- /R/help.R: -------------------------------------------------------------------------------- 1 | #' A package for creating parallel coordinates for categorical data 2 | #' 3 | #' The main function \code{\link{ggparallel}} implements three types of 4 | #' parallel coordinate plots for categorical data: hammock plots, parallel 5 | #' sets plots, and common angle plots. 6 | #' 7 | #' @docType package 8 | #' @name package-ggparallel 9 | NULL 10 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | ``` 15 | 16 | # ggparallel 17 | 18 | 19 | [![CRAN status](https://www.r-pkg.org/badges/version/ggparallel)](https://CRAN.R-project.org/package=ggparallel) 20 | [![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/last-month/ggparallel?color=blue)](https://r-pkg.org/pkg/ggparallel) 21 | [![Last-changedate](https://img.shields.io/badge/last%20change-`r gsub('-', '--', Sys.Date())`-yellowgreen.svg)](https://github.com/heike/ggparallel/commits/main) 22 | [![codecov test coverage](https://codecov.io/gh/heike/ggparallel/graph/badge.svg?token=zfeqffIjxY)](https://codecov.io/gh/heike/ggparallel) 23 | [![R-CMD-check](https://github.com/heike/ggparallel/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/heike/ggparallel/actions/workflows/R-CMD-check.yaml) 24 | 25 | 26 | 27 | The R package `ggparallel` implements and combines different types of parallel coordinate plots for categorical data: [hammock plots](http://www.schonlau.net/publication/03jsm_hammockplot_old.pdf), [parallel sets plots](https://datavizcatalogue.com/methods/parallel_sets.html), and [common angle plots](https://ieeexplore.ieee.org/document/6634157), as well as common angle plots with a hammock-like adjustment for line widths. 28 | 29 | ## Installation 30 | 31 | The package is available on CRAN: 32 | 33 | ``` 34 | install.packages("ggparallel") 35 | ``` 36 | 37 | You can install the development version of ggparallel from [GitHub](https://github.com/) with: 38 | 39 | ``` 40 | # install.packages("remotes") 41 | remotes::install_github("heike/ggparallel") 42 | ``` 43 | 44 | ## Basic use case 45 | 46 | 47 | 48 | ```{r} 49 | library(ggparallel) 50 | data(mtcars) 51 | 52 | ggparallel(list("gear", "cyl"), data=mtcars) 53 | ``` 54 | 55 | 56 | ```{r} 57 | ggparallel(list("gear", "cyl"), data=mtcars, method="hammock", ratio=0.25) 58 | ``` 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # ggparallel 5 | 6 | 7 | 8 | [![CRAN 9 | status](https://www.r-pkg.org/badges/version/ggparallel)](https://CRAN.R-project.org/package=ggparallel) 10 | [![CRAN RStudio mirror 11 | downloads](https://cranlogs.r-pkg.org/badges/last-month/ggparallel?color=blue)](https://r-pkg.org/pkg/ggparallel) 12 | [![Last-changedate](https://img.shields.io/badge/last%20change-2024--01--29-yellowgreen.svg)](https://github.com/heike/ggparallel/commits/main) 13 | [![codecov test 14 | coverage](https://codecov.io/gh/heike/ggparallel/graph/badge.svg?token=zfeqffIjxY)](https://codecov.io/gh/heike/ggparallel) 15 | [![R-CMD-check](https://github.com/heike/ggparallel/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/heike/ggparallel/actions/workflows/R-CMD-check.yaml) 16 | 17 | 18 | The R package `ggparallel` implements and combines different types of 19 | parallel coordinate plots for categorical data: [hammock 20 | plots](http://www.schonlau.net/publication/03jsm_hammockplot_old.pdf), 21 | [parallel sets 22 | plots](https://datavizcatalogue.com/methods/parallel_sets.html), and 23 | [common angle plots](https://ieeexplore.ieee.org/document/6634157), as 24 | well as common angle plots with a hammock-like adjustment for line 25 | widths. 26 | 27 | ## Installation 28 | 29 | The package is available on CRAN: 30 | 31 | install.packages("ggparallel") 32 | 33 | You can install the development version of ggparallel from 34 | [GitHub](https://github.com/) with: 35 | 36 | # install.packages("remotes") 37 | remotes::install_github("heike/ggparallel") 38 | 39 | ## Basic use case 40 | 41 | ``` r 42 | library(ggparallel) 43 | #> Loading required package: ggplot2 44 | data(mtcars) 45 | 46 | ggparallel(list("gear", "cyl"), data=mtcars) 47 | ``` 48 | 49 | 50 | 51 | ``` r 52 | ggparallel(list("gear", "cyl"), data=mtcars, method="hammock", ratio=0.25) 53 | ``` 54 | 55 | 56 | -------------------------------------------------------------------------------- /README_files/figure-html/unnamed-chunk-1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/README_files/figure-html/unnamed-chunk-1-1.png -------------------------------------------------------------------------------- /README_files/figure-html/unnamed-chunk-1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/README_files/figure-html/unnamed-chunk-1-2.png -------------------------------------------------------------------------------- /README_files/figure-markdown_strict/unnamed-chunk-1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/README_files/figure-markdown_strict/unnamed-chunk-1-1.png -------------------------------------------------------------------------------- /README_files/figure-markdown_strict/unnamed-chunk-1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/README_files/figure-markdown_strict/unnamed-chunk-1-2.png -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://heike.github.io/ggparallel/ 2 | template: 3 | bootstrap: 5 4 | 5 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | * local OS X install, R 4.3.2 3 | * ubuntu 22.04 (on Github actions), R 4.3.2 4 | * win-builder (devel and release) 5 | 6 | ## R CMD check results 7 | There were no ERRORs, WARNINGs or NOTEs. 8 | 9 | ## Downstream dependencies 10 | There are no reverse dependencies. 11 | -------------------------------------------------------------------------------- /data/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/data/.DS_Store -------------------------------------------------------------------------------- /data/genes.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/data/genes.rda -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Page not found (404) • ggparallel 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | Skip to contents 21 | 22 | 23 |
60 |
61 |
65 | 66 | Content not found. Please use links in the navbar. 67 | 68 |
69 |
70 | 71 | 72 | 83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | License • ggparallel 6 | Skip to contents 7 | 8 | 9 |
41 |
42 |
46 | 47 |
YEAR: 2012-2024
48 | COPYRIGHT HOLDER: Heike Hofmann; Marie Vendettuoli
49 | 
50 | 51 |
52 | 53 | 54 |
63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | Authors and Citation • ggparallel 6 | Skip to contents 7 | 8 | 9 |
41 |
42 |
45 | 46 |
47 |

Authors

48 | 49 |
  • 50 |

    Heike Hofmann. Author, maintainer. 51 |

    52 |
  • 53 |
  • 54 |

    Marie Vendettuoli. Author. 55 |

    56 |
  • 57 |
58 | 59 |
60 |

Citation

61 |

Source: inst/CITATION

62 | 63 |

Hofmann H, Vendettuoli M (2013). 64 | “Common Angle Plots as Perception-True Visualizations of Categorical Associations.” 65 | IEEE Transactions on Visualization & Computer Graphics, 2297–2305. 66 | doi:10.1109/TVCG.2013.140. 67 |

68 |
@Article{,
69 |   title = {Common Angle Plots as Perception-True Visualizations of Categorical Associations},
70 |   author = {Heike Hofmann and Marie Vendettuoli},
71 |   journal = {IEEE Transactions on Visualization & Computer Graphics},
72 |   year = {2013},
73 |   number = {12},
74 |   pages = {2297--2305},
75 |   doi = {10.1109/TVCG.2013.140},
76 | }
77 |
78 |
80 | 81 | 82 |
91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/docsearch.css: -------------------------------------------------------------------------------- 1 | /* Docsearch -------------------------------------------------------------- */ 2 | /* 3 | Source: https://github.com/algolia/docsearch/ 4 | License: MIT 5 | */ 6 | 7 | .algolia-autocomplete { 8 | display: block; 9 | -webkit-box-flex: 1; 10 | -ms-flex: 1; 11 | flex: 1 12 | } 13 | 14 | .algolia-autocomplete .ds-dropdown-menu { 15 | width: 100%; 16 | min-width: none; 17 | max-width: none; 18 | padding: .75rem 0; 19 | background-color: #fff; 20 | background-clip: padding-box; 21 | border: 1px solid rgba(0, 0, 0, .1); 22 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); 23 | } 24 | 25 | @media (min-width:768px) { 26 | .algolia-autocomplete .ds-dropdown-menu { 27 | width: 175% 28 | } 29 | } 30 | 31 | .algolia-autocomplete .ds-dropdown-menu::before { 32 | display: none 33 | } 34 | 35 | .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { 36 | padding: 0; 37 | background-color: rgb(255,255,255); 38 | border: 0; 39 | max-height: 80vh; 40 | } 41 | 42 | .algolia-autocomplete .ds-dropdown-menu .ds-suggestions { 43 | margin-top: 0 44 | } 45 | 46 | .algolia-autocomplete .algolia-docsearch-suggestion { 47 | padding: 0; 48 | overflow: visible 49 | } 50 | 51 | .algolia-autocomplete .algolia-docsearch-suggestion--category-header { 52 | padding: .125rem 1rem; 53 | margin-top: 0; 54 | font-size: 1.3em; 55 | font-weight: 500; 56 | color: #00008B; 57 | border-bottom: 0 58 | } 59 | 60 | .algolia-autocomplete .algolia-docsearch-suggestion--wrapper { 61 | float: none; 62 | padding-top: 0 63 | } 64 | 65 | .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { 66 | float: none; 67 | width: auto; 68 | padding: 0; 69 | text-align: left 70 | } 71 | 72 | .algolia-autocomplete .algolia-docsearch-suggestion--content { 73 | float: none; 74 | width: auto; 75 | padding: 0 76 | } 77 | 78 | .algolia-autocomplete .algolia-docsearch-suggestion--content::before { 79 | display: none 80 | } 81 | 82 | .algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { 83 | padding-top: .75rem; 84 | margin-top: .75rem; 85 | border-top: 1px solid rgba(0, 0, 0, .1) 86 | } 87 | 88 | .algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { 89 | display: block; 90 | padding: .1rem 1rem; 91 | margin-bottom: 0.1; 92 | font-size: 1.0em; 93 | font-weight: 400 94 | /* display: none */ 95 | } 96 | 97 | .algolia-autocomplete .algolia-docsearch-suggestion--title { 98 | display: block; 99 | padding: .25rem 1rem; 100 | margin-bottom: 0; 101 | font-size: 0.9em; 102 | font-weight: 400 103 | } 104 | 105 | .algolia-autocomplete .algolia-docsearch-suggestion--text { 106 | padding: 0 1rem .5rem; 107 | margin-top: -.25rem; 108 | font-size: 0.8em; 109 | font-weight: 400; 110 | line-height: 1.25 111 | } 112 | 113 | .algolia-autocomplete .algolia-docsearch-footer { 114 | width: 110px; 115 | height: 20px; 116 | z-index: 3; 117 | margin-top: 10.66667px; 118 | float: right; 119 | font-size: 0; 120 | line-height: 0; 121 | } 122 | 123 | .algolia-autocomplete .algolia-docsearch-footer--logo { 124 | background-image: url("data:image/svg+xml;utf8,"); 125 | background-repeat: no-repeat; 126 | background-position: 50%; 127 | background-size: 100%; 128 | overflow: hidden; 129 | text-indent: -9000px; 130 | width: 100%; 131 | height: 100%; 132 | display: block; 133 | transform: translate(-8px); 134 | } 135 | 136 | .algolia-autocomplete .algolia-docsearch-suggestion--highlight { 137 | color: #FF8C00; 138 | background: rgba(232, 189, 54, 0.1) 139 | } 140 | 141 | 142 | .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { 143 | box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) 144 | } 145 | 146 | .algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { 147 | background-color: rgba(192, 192, 192, .15) 148 | } 149 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | Variations of Parallel Coordinate Plots for Categorical Data • ggparallel 11 | 12 | 13 | 14 | 15 | 16 | 18 | 22 | 23 | 24 | Skip to contents 25 | 26 | 27 |
    64 |
    65 |
    66 | 68 | 69 | 70 |

    The R package ggparallel implements and combines different types of parallel coordinate plots for categorical data: hammock plots, parallel sets plots, and common angle plots, as well as common angle plots with a hammock-like adjustment for line widths.

    71 |
    72 |

    Installation 73 |

    74 |

    The package is available on CRAN:

    75 |
    install.packages("ggparallel")
    76 |

    You can install the development version of ggparallel from GitHub with:

    77 |
    # install.packages("remotes")
     78 | remotes::install_github("heike/ggparallel")
    79 |
    80 |
    81 |

    Basic use case 82 |

    83 |
     84 | library(ggparallel)
     85 | #> Loading required package: ggplot2
     86 | data(mtcars)
     87 | 
     88 | ggparallel(list("gear", "cyl"), data=mtcars)
    89 |

    90 |
     91 | ggparallel(list("gear", "cyl"), data=mtcars, method="hammock", ratio=0.25)
    92 |

    93 |
    94 |
    95 |
    141 |
    142 | 143 | 144 |
    148 | 149 | 153 | 154 |
    155 |
    156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/news/index.html: -------------------------------------------------------------------------------- 1 | 2 | Changelog • ggparallel 6 | Skip to contents 7 | 8 | 9 |
    41 |
    42 |
    46 | 47 |
    48 |

    ggparallel 0.3.0

    49 |
    • Required change to package documentation.
    • 50 |
    51 |
    52 |

    ggparallel 0.2.0

    CRAN release: 2016-12-05

    53 |
    • Added a NEWS.md file to track changes to the package.
    • 54 |
    55 |
    57 | 58 | 59 |
    62 | 63 | 66 | 67 |
    68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body { 21 | position: relative; 22 | } 23 | 24 | body > .container { 25 | display: flex; 26 | height: 100%; 27 | flex-direction: column; 28 | } 29 | 30 | body > .container .row { 31 | flex: 1 0 auto; 32 | } 33 | 34 | footer { 35 | margin-top: 45px; 36 | padding: 35px 0 36px; 37 | border-top: 1px solid #e5e5e5; 38 | color: #666; 39 | display: flex; 40 | flex-shrink: 0; 41 | } 42 | footer p { 43 | margin-bottom: 0; 44 | } 45 | footer div { 46 | flex: 1; 47 | } 48 | footer .pkgdown { 49 | text-align: right; 50 | } 51 | footer p { 52 | margin-bottom: 0; 53 | } 54 | 55 | img.icon { 56 | float: right; 57 | } 58 | 59 | /* Ensure in-page images don't run outside their container */ 60 | .contents img { 61 | max-width: 100%; 62 | height: auto; 63 | } 64 | 65 | /* Fix bug in bootstrap (only seen in firefox) */ 66 | summary { 67 | display: list-item; 68 | } 69 | 70 | /* Typographic tweaking ---------------------------------*/ 71 | 72 | .contents .page-header { 73 | margin-top: calc(-60px + 1em); 74 | } 75 | 76 | dd { 77 | margin-left: 3em; 78 | } 79 | 80 | /* Section anchors ---------------------------------*/ 81 | 82 | a.anchor { 83 | display: none; 84 | margin-left: 5px; 85 | width: 20px; 86 | height: 20px; 87 | 88 | background-image: url(./link.svg); 89 | background-repeat: no-repeat; 90 | background-size: 20px 20px; 91 | background-position: center center; 92 | } 93 | 94 | h1:hover .anchor, 95 | h2:hover .anchor, 96 | h3:hover .anchor, 97 | h4:hover .anchor, 98 | h5:hover .anchor, 99 | h6:hover .anchor { 100 | display: inline-block; 101 | } 102 | 103 | /* Fixes for fixed navbar --------------------------*/ 104 | 105 | .contents h1, .contents h2, .contents h3, .contents h4 { 106 | padding-top: 60px; 107 | margin-top: -40px; 108 | } 109 | 110 | /* Navbar submenu --------------------------*/ 111 | 112 | .dropdown-submenu { 113 | position: relative; 114 | } 115 | 116 | .dropdown-submenu>.dropdown-menu { 117 | top: 0; 118 | left: 100%; 119 | margin-top: -6px; 120 | margin-left: -1px; 121 | border-radius: 0 6px 6px 6px; 122 | } 123 | 124 | .dropdown-submenu:hover>.dropdown-menu { 125 | display: block; 126 | } 127 | 128 | .dropdown-submenu>a:after { 129 | display: block; 130 | content: " "; 131 | float: right; 132 | width: 0; 133 | height: 0; 134 | border-color: transparent; 135 | border-style: solid; 136 | border-width: 5px 0 5px 5px; 137 | border-left-color: #cccccc; 138 | margin-top: 5px; 139 | margin-right: -10px; 140 | } 141 | 142 | .dropdown-submenu:hover>a:after { 143 | border-left-color: #ffffff; 144 | } 145 | 146 | .dropdown-submenu.pull-left { 147 | float: none; 148 | } 149 | 150 | .dropdown-submenu.pull-left>.dropdown-menu { 151 | left: -100%; 152 | margin-left: 10px; 153 | border-radius: 6px 0 6px 6px; 154 | } 155 | 156 | /* Sidebar --------------------------*/ 157 | 158 | #pkgdown-sidebar { 159 | margin-top: 30px; 160 | position: -webkit-sticky; 161 | position: sticky; 162 | top: 70px; 163 | } 164 | 165 | #pkgdown-sidebar h2 { 166 | font-size: 1.5em; 167 | margin-top: 1em; 168 | } 169 | 170 | #pkgdown-sidebar h2:first-child { 171 | margin-top: 0; 172 | } 173 | 174 | #pkgdown-sidebar .list-unstyled li { 175 | margin-bottom: 0.5em; 176 | } 177 | 178 | /* bootstrap-toc tweaks ------------------------------------------------------*/ 179 | 180 | /* All levels of nav */ 181 | 182 | nav[data-toggle='toc'] .nav > li > a { 183 | padding: 4px 20px 4px 6px; 184 | font-size: 1.5rem; 185 | font-weight: 400; 186 | color: inherit; 187 | } 188 | 189 | nav[data-toggle='toc'] .nav > li > a:hover, 190 | nav[data-toggle='toc'] .nav > li > a:focus { 191 | padding-left: 5px; 192 | color: inherit; 193 | border-left: 1px solid #878787; 194 | } 195 | 196 | nav[data-toggle='toc'] .nav > .active > a, 197 | nav[data-toggle='toc'] .nav > .active:hover > a, 198 | nav[data-toggle='toc'] .nav > .active:focus > a { 199 | padding-left: 5px; 200 | font-size: 1.5rem; 201 | font-weight: 400; 202 | color: inherit; 203 | border-left: 2px solid #878787; 204 | } 205 | 206 | /* Nav: second level (shown on .active) */ 207 | 208 | nav[data-toggle='toc'] .nav .nav { 209 | display: none; /* Hide by default, but at >768px, show it */ 210 | padding-bottom: 10px; 211 | } 212 | 213 | nav[data-toggle='toc'] .nav .nav > li > a { 214 | padding-left: 16px; 215 | font-size: 1.35rem; 216 | } 217 | 218 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 219 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 220 | padding-left: 15px; 221 | } 222 | 223 | nav[data-toggle='toc'] .nav .nav > .active > a, 224 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 225 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 226 | padding-left: 15px; 227 | font-weight: 500; 228 | font-size: 1.35rem; 229 | } 230 | 231 | /* orcid ------------------------------------------------------------------- */ 232 | 233 | .orcid { 234 | font-size: 16px; 235 | color: #A6CE39; 236 | /* margins are required by official ORCID trademark and display guidelines */ 237 | margin-left:4px; 238 | margin-right:4px; 239 | vertical-align: middle; 240 | } 241 | 242 | /* Reference index & topics ----------------------------------------------- */ 243 | 244 | .ref-index th {font-weight: normal;} 245 | 246 | .ref-index td {vertical-align: top; min-width: 100px} 247 | .ref-index .icon {width: 40px;} 248 | .ref-index .alias {width: 40%;} 249 | .ref-index-icons .alias {width: calc(40% - 40px);} 250 | .ref-index .title {width: 60%;} 251 | 252 | .ref-arguments th {text-align: right; padding-right: 10px;} 253 | .ref-arguments th, .ref-arguments td {vertical-align: top; min-width: 100px} 254 | .ref-arguments .name {width: 20%;} 255 | .ref-arguments .desc {width: 80%;} 256 | 257 | /* Nice scrolling for wide elements --------------------------------------- */ 258 | 259 | table { 260 | display: block; 261 | overflow: auto; 262 | } 263 | 264 | /* Syntax highlighting ---------------------------------------------------- */ 265 | 266 | pre, code, pre code { 267 | background-color: #f8f8f8; 268 | color: #333; 269 | } 270 | pre, pre code { 271 | white-space: pre-wrap; 272 | word-break: break-all; 273 | overflow-wrap: break-word; 274 | } 275 | 276 | pre { 277 | border: 1px solid #eee; 278 | } 279 | 280 | pre .img, pre .r-plt { 281 | margin: 5px 0; 282 | } 283 | 284 | pre .img img, pre .r-plt img { 285 | background-color: #fff; 286 | } 287 | 288 | code a, pre a { 289 | color: #375f84; 290 | } 291 | 292 | a.sourceLine:hover { 293 | text-decoration: none; 294 | } 295 | 296 | .fl {color: #1514b5;} 297 | .fu {color: #000000;} /* function */ 298 | .ch,.st {color: #036a07;} /* string */ 299 | .kw {color: #264D66;} /* keyword */ 300 | .co {color: #888888;} /* comment */ 301 | 302 | .error {font-weight: bolder;} 303 | .warning {font-weight: bolder;} 304 | 305 | /* Clipboard --------------------------*/ 306 | 307 | .hasCopyButton { 308 | position: relative; 309 | } 310 | 311 | .btn-copy-ex { 312 | position: absolute; 313 | right: 0; 314 | top: 0; 315 | visibility: hidden; 316 | } 317 | 318 | .hasCopyButton:hover button.btn-copy-ex { 319 | visibility: visible; 320 | } 321 | 322 | /* headroom.js ------------------------ */ 323 | 324 | .headroom { 325 | will-change: transform; 326 | transition: transform 200ms linear; 327 | } 328 | .headroom--pinned { 329 | transform: translateY(0%); 330 | } 331 | .headroom--unpinned { 332 | transform: translateY(-100%); 333 | } 334 | 335 | /* mark.js ----------------------------*/ 336 | 337 | mark { 338 | background-color: rgba(255, 255, 51, 0.5); 339 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 340 | padding: 1px; 341 | } 342 | 343 | /* vertical spacing after htmlwidgets */ 344 | .html-widget { 345 | margin-bottom: 10px; 346 | } 347 | 348 | /* fontawesome ------------------------ */ 349 | 350 | .fab { 351 | font-family: "Font Awesome 5 Brands" !important; 352 | } 353 | 354 | /* don't display links in code chunks when printing */ 355 | /* source: https://stackoverflow.com/a/10781533 */ 356 | @media print { 357 | code a:link:after, code a:visited:after { 358 | content: ""; 359 | } 360 | } 361 | 362 | /* Section anchors --------------------------------- 363 | Added in pandoc 2.11: https://github.com/jgm/pandoc-templates/commit/9904bf71 364 | */ 365 | 366 | div.csl-bib-body { } 367 | div.csl-entry { 368 | clear: both; 369 | } 370 | .hanging-indent div.csl-entry { 371 | margin-left:2em; 372 | text-indent:-2em; 373 | } 374 | div.csl-left-margin { 375 | min-width:2em; 376 | float:left; 377 | } 378 | div.csl-right-inline { 379 | margin-left:2em; 380 | padding-left:1em; 381 | } 382 | div.csl-indent { 383 | margin-left: 2em; 384 | } 385 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('nav.navbar').headroom(); 6 | 7 | Toc.init({ 8 | $nav: $("#toc"), 9 | $scope: $("main h2, main h3, main h4, main h5, main h6") 10 | }); 11 | 12 | if ($('#toc').length) { 13 | $('body').scrollspy({ 14 | target: '#toc', 15 | offset: $("nav.navbar").outerHeight() + 1 16 | }); 17 | } 18 | 19 | // Activate popovers 20 | $('[data-bs-toggle="popover"]').popover({ 21 | container: 'body', 22 | html: true, 23 | trigger: 'focus', 24 | placement: "top", 25 | sanitize: false, 26 | }); 27 | 28 | $('[data-bs-toggle="tooltip"]').tooltip(); 29 | 30 | /* Clipboard --------------------------*/ 31 | 32 | function changeTooltipMessage(element, msg) { 33 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 34 | element.setAttribute('data-original-title', msg); 35 | $(element).tooltip('show'); 36 | element.setAttribute('data-original-title', tooltipOriginalTitle); 37 | } 38 | 39 | if(ClipboardJS.isSupported()) { 40 | $(document).ready(function() { 41 | var copyButton = ""; 42 | 43 | $("div.sourceCode").addClass("hasCopyButton"); 44 | 45 | // Insert copy buttons: 46 | $(copyButton).prependTo(".hasCopyButton"); 47 | 48 | // Initialize tooltips: 49 | $('.btn-copy-ex').tooltip({container: 'body'}); 50 | 51 | // Initialize clipboard: 52 | var clipboard = new ClipboardJS('[data-clipboard-copy]', { 53 | text: function(trigger) { 54 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 55 | } 56 | }); 57 | 58 | clipboard.on('success', function(e) { 59 | changeTooltipMessage(e.trigger, 'Copied!'); 60 | e.clearSelection(); 61 | }); 62 | 63 | clipboard.on('error', function() { 64 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 65 | }); 66 | 67 | }); 68 | } 69 | 70 | /* Search marking --------------------------*/ 71 | var url = new URL(window.location.href); 72 | var toMark = url.searchParams.get("q"); 73 | var mark = new Mark("main#main"); 74 | if (toMark) { 75 | mark.mark(toMark, { 76 | accuracy: { 77 | value: "complementary", 78 | limiters: [",", ".", ":", "/"], 79 | } 80 | }); 81 | } 82 | 83 | /* Search --------------------------*/ 84 | /* Adapted from https://github.com/rstudio/bookdown/blob/2d692ba4b61f1e466c92e78fd712b0ab08c11d31/inst/resources/bs4_book/bs4_book.js#L25 */ 85 | // Initialise search index on focus 86 | var fuse; 87 | $("#search-input").focus(async function(e) { 88 | if (fuse) { 89 | return; 90 | } 91 | 92 | $(e.target).addClass("loading"); 93 | var response = await fetch($("#search-input").data("search-index")); 94 | var data = await response.json(); 95 | 96 | var options = { 97 | keys: ["what", "text", "code"], 98 | ignoreLocation: true, 99 | threshold: 0.1, 100 | includeMatches: true, 101 | includeScore: true, 102 | }; 103 | fuse = new Fuse(data, options); 104 | 105 | $(e.target).removeClass("loading"); 106 | }); 107 | 108 | // Use algolia autocomplete 109 | var options = { 110 | autoselect: true, 111 | debug: true, 112 | hint: false, 113 | minLength: 2, 114 | }; 115 | var q; 116 | async function searchFuse(query, callback) { 117 | await fuse; 118 | 119 | var items; 120 | if (!fuse) { 121 | items = []; 122 | } else { 123 | q = query; 124 | var results = fuse.search(query, { limit: 20 }); 125 | items = results 126 | .filter((x) => x.score <= 0.75) 127 | .map((x) => x.item); 128 | if (items.length === 0) { 129 | items = [{dir:"Sorry 😿",previous_headings:"",title:"No results found.",what:"No results found.",path:window.location.href}]; 130 | } 131 | } 132 | callback(items); 133 | } 134 | $("#search-input").autocomplete(options, [ 135 | { 136 | name: "content", 137 | source: searchFuse, 138 | templates: { 139 | suggestion: (s) => { 140 | if (s.title == s.what) { 141 | return `${s.dir} >
    ${s.title}
    `; 142 | } else if (s.previous_headings == "") { 143 | return `${s.dir} >
    ${s.title}
    > ${s.what}`; 144 | } else { 145 | return `${s.dir} >
    ${s.title}
    > ${s.previous_headings} > ${s.what}`; 146 | } 147 | }, 148 | }, 149 | }, 150 | ]).on('autocomplete:selected', function(event, s) { 151 | window.location.href = s.path + "?q=" + q + "#" + s.id; 152 | }); 153 | }); 154 | })(window.jQuery || window.$) 155 | 156 | 157 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 3.1.6.1 2 | pkgdown: 2.0.7 3 | pkgdown_sha: ~ 4 | articles: {} 5 | last_built: 2024-01-29T16:22Z 6 | urls: 7 | reference: https://heike.github.io/ggparallel/reference 8 | article: https://heike.github.io/ggparallel/articles 9 | 10 | -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /docs/reference/Rplot002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot002.png -------------------------------------------------------------------------------- /docs/reference/Rplot003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot003.png -------------------------------------------------------------------------------- /docs/reference/Rplot004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot004.png -------------------------------------------------------------------------------- /docs/reference/Rplot005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot005.png -------------------------------------------------------------------------------- /docs/reference/Rplot006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot006.png -------------------------------------------------------------------------------- /docs/reference/Rplot007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot007.png -------------------------------------------------------------------------------- /docs/reference/Rplot008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot008.png -------------------------------------------------------------------------------- /docs/reference/Rplot009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot009.png -------------------------------------------------------------------------------- /docs/reference/Rplot010.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/Rplot010.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/figures/README-unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/reference/genes-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/genes-1.png -------------------------------------------------------------------------------- /docs/reference/genes.html: -------------------------------------------------------------------------------- 1 | 2 | Data linking genes and pathways. — genes • ggparallel 14 | Skip to contents 15 | 16 | 17 |
    49 |
    50 |
    55 | 56 |
    57 |

    Table knownGene from track UCSC Genes was downloaded from the UCSC table 58 | browser for the human genome assembly (hg18, May 2006) and filtered for a 59 | selection of pathways associated with human metabolism was obtained from KEGG 60 | PATHWAY database. Bioconductor package KEGG.db was used to provide mappings 61 | between gene and pathway identifiers.

    62 |
    63 | 64 |
    65 |

    Usage

    66 |
    genes
    67 |
    68 | 69 |
    70 |

    Format

    71 |

    An object of class data.frame with 2768 rows and 14 columns.

    72 |
    73 |
    74 |

    References

    75 |

    Fujita PA, Rhead B, Zweig AS, Hinrichs AS, Karolchik D, Cline MS, 76 | Goldman M, Barber GP, Clawson H, Coelho A, Diekhans M, Dreszer TR, Giardine 77 | BM, Harte RA, Hillman-Jackson J, Hsu F, Kirkup V, Kuhn RM, Learned K, Li CH, 78 | Meyer LR, Pohl A, Raney BJ, Rosenbloom KR, Smith KE, Haussler D, Kent WJ. The 79 | UCSC Genome Browser database: update 2011. Nucleic Acids Res. 2010 Oct 18. 80 | http://genome.ucsc.edu/index.html?org=Human&db=hg19&hgsid=289810087

    81 |

    Marc Carlson, Seth Falcon, Herve Pages and Nianhua Li (). KEGG.db: A set 82 | of annotation maps for KEGG. R package version 2.6.1.

    83 |

    Kanehisa, M., Goto, S., Sato, Y., Furumichi, M., and Tanabe, M.; KEGG for 84 | integration and interpretation of large-scale molecular datasets. Nucleic 85 | Acids Res. 40, D109-D114 (2012)

    86 |

    Kanehisa, M. and Goto, S.; KEGG: Kyoto Encyclopedia of Genes and Genomes. 87 | Nucleic Acids Res. 28, 27-30 (2000).

    88 |
    89 | 90 |
    91 |

    Examples

    92 |
    library(ggplot2)
     93 | library(RColorBrewer)
     94 | genes$chrom <- factor(genes$chrom, levels=c(paste("chr", 1:22, sep=""),
     95 |   "chrX", "chrY"))
     96 | ggparallel(
     97 |   list("path", "chrom"),
     98 |   text.offset = c(0.03, 0,-0.03),
     99 |   data = genes,
    100 |   width = 0.1,
    101 |   order = c(1, 0),
    102 |   angle = 0,
    103 |   color = "white",
    104 |   factorlevels =  c(sapply(unique(genes$chrom), as.character),unique(genes$path))
    105 | ) +
    106 |  scale_fill_manual(
    107 |    values = c(brewer.pal("YlOrRd", n = 9), rep("grey80", 24)),
    108 |    guide = "none"
    109 |  ) +
    110 |  scale_colour_manual(
    111 |    values = c(brewer.pal("YlOrRd", n = 9), rep("grey80", 24)),
    112 |    guide = "none"
    113 |  ) +
    114 |  coord_flip()
    115 | 
    116 | 
    117 |
    118 |
    120 | 121 | 122 |
    125 | 126 | 129 | 130 |
    131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /docs/reference/ggparallel-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-1.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-10.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-2.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-3.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-4.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-5.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-6.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-7.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-8.png -------------------------------------------------------------------------------- /docs/reference/ggparallel-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/docs/reference/ggparallel-9.png -------------------------------------------------------------------------------- /docs/reference/ggparallel.html: -------------------------------------------------------------------------------- 1 | 2 | Variations of parallel coordinate plots — ggparallel • ggparallel 12 | Skip to contents 13 | 14 | 15 |
    47 |
    48 |
    53 | 54 |
    55 |

    ggparallel implements and combines different types of parallel 56 | coordinate plots for categorical data: hammock plots, parallel sets plots, 57 | common angle plots, and common angle plots with a hammock-like adjustment 58 | for line widths.

    59 |
    60 | 61 |
    62 |

    Usage

    63 |
    ggparallel(
     64 |   vars = list(),
     65 |   data,
     66 |   weight = NULL,
     67 |   method = "angle",
     68 |   alpha = 0.5,
     69 |   width = 0.25,
     70 |   order = 1,
     71 |   ratio = NULL,
     72 |   asp = NULL,
     73 |   label = TRUE,
     74 |   label.colour = "grey90",
     75 |   label.size = 4,
     76 |   text.angle = 90,
     77 |   text.offset = NULL,
     78 |   same.level = FALSE,
     79 |   ...
     80 | )
    81 |
    82 | 83 |
    84 |

    Arguments

    85 |
    vars
    86 |

    list of variable names to be included in the plotting. Order of 87 | the variables is preserved in the display

    88 | 89 | 90 |
    data
    91 |

    data frame

    92 | 93 | 94 |
    weight
    95 |

    weighting variable - use character string

    96 | 97 | 98 |
    method
    99 |

    plotting method to use - one of angle, 100 | adj.angle, parset, or hammock, for a hammock plot 101 | the aspect ratio needs to be fixed.

    102 | 103 | 104 |
    alpha
    105 |

    level of alpha blending for the fill color in ribbons, value 106 | has to be between 0 and 1, defaults to 0.5.

    107 | 108 | 109 |
    width
    110 |

    width of variables

    111 | 112 | 113 |
    order
    114 |

    flag variable with three levels -1, 0, 1 for levels in 115 | decreasing order, levels in increasing order and levels unchanged. This 116 | variable can be either a scalar or a vector

    117 | 118 | 119 |
    ratio
    120 |

    used for methods with angle adjustments (method = 121 | 'hammock', 'adj.angle'): specifies the height (width for horizontal 122 | displays) of the widest line as ratio of the overall display height (width 123 | for horizontal displays).

    124 | 125 | 126 |
    asp
    127 |

    aspect ratio of the plot - it will be set to a default of 1 in 128 | the case of hammock plots.

    129 | 130 | 131 |
    label
    132 |

    binary variable (vector), whether labels should be shown.

    133 | 134 | 135 |
    label.colour
    136 |

    character of colour in which the label should be shown. Ignored, if `label` is FALSE.

    137 | 138 | 139 |
    label.size
    140 |

    numeric value to determine the size in which labels are shown, defaults to 4

    141 | 142 | 143 |
    text.angle
    144 |

    numeric value to determine the angle under which labels are shown.

    145 | 146 | 147 |
    text.offset
    148 |

    (vector) of values for offsetting the labels

    149 | 150 | 151 |
    same.level
    152 |

    are all variables using the same levels? If yes, simplify the labelling

    153 | 154 | 155 |
    ...
    156 |

    passed on directly to all of the ggplot2 commands

    157 | 158 |
    159 |
    160 |

    Value

    161 | 162 | 163 |

    returns a ggplot2 object that can be plotted directly or used as base 164 | layer for additional modifications.

    165 |
    166 |
    167 |

    Details

    168 |

    Parallel sets have been suggested by kosara:2006 as a visualization 169 | technique to incorporate categorical variables into a parallel coordinate 170 | plot introduced by wegman:1990 and inselberg:1985. The parallel 171 | sets implemented here are reduced to representations of neighboring 172 | two-dimensional relationships only rather than the hierarchical version 173 | originally suggested.

    174 |

    Both versions, however, show perceptual problems with interpreting line 175 | widths, leading to potentially wrong conclusions about the data. The hammock 176 | display, introduced by schonlau:2003, and the common angle plots are 177 | two approaches at fixing this problem: in Hammock plots the linewidth is 178 | adjusted by a factor countering the strength of the illusion, in the common 179 | angle plot all lines are adjusted to show the same angle - making line widths 180 | again comparable across ribbons.

    181 |

    Additionally, we can also adjust ribbons in the common angle display for the 182 | angle, to make them appear having the same width (or height) across the 183 | display. We refer to this method as adj.angle.

    184 |
    185 | 186 |
    187 |

    Examples

    188 |
    data(mtcars)
    189 | 
    190 | ggparallel(list("gear", "cyl"), data=mtcars)
    191 | 
    192 | ggparallel(list("gear", "cyl"), data=mtcars, method="hammock", ratio=0.25)
    193 | 
    194 | 
    195 | require(RColorBrewer)
    196 | require(ggplot2)
    197 | cols <- c(brewer.pal(4, "Reds")[-1], brewer.pal(4, "Blues")[-1])
    198 | ggparallel(list("gear", "cyl"), ratio=0.2, data=mtcars,
    199 |            method="hammock", text.angle=0) +
    200 |   scale_fill_manual(values=cols) + scale_colour_manual(values=cols) +
    201 |   theme_bw()
    202 | 
    203 | 
    204 | ## combination of common angle plot and hammock adjustment:
    205 | ggparallel(list("gear", "cyl"), data=mtcars, method="adj.angle",
    206 |            ratio=2)
    207 | 
    208 | 
    209 | ## compare with method='parset'
    210 | ggparallel(list("gear", "cyl"), data=mtcars, method='parset')
    211 | 
    212 | 
    213 | ## flip plot and rotate text
    214 | ggparallel(list("gear", "cyl"), data=mtcars, text.angle=0) +
    215 |   coord_flip()
    216 | 
    217 | 
    218 | ## change colour scheme
    219 | ggparallel(list("gear", "cyl"), data=mtcars, text.angle=0) +
    220 |   coord_flip() +
    221 |   scale_fill_brewer(palette="Set1") +
    222 |   scale_colour_brewer(palette="Set1")
    223 | 
    224 | 
    225 | ## example with more than two variables:
    226 | titanic <- as.data.frame(Titanic)
    227 | ggparallel(names(titanic)[c(1,4,2,1)], order=0, titanic, weight="Freq") +
    228 |   scale_fill_brewer(palette="Paired", guide="none") +
    229 |   scale_colour_brewer(palette="Paired", guide="none")
    230 | #> Warning: attributes are not identical across measure variables; they will be dropped
    231 | 
    232 | 
    233 | if (FALSE) {
    234 | cols <- c(brewer.pal(5,"Blues")[-1], brewer.pal(3, "Oranges")[-1],
    235 |           brewer.pal(3, "Greens")[-1])
    236 | ggparallel(names(titanic)[c(1,4,2,1)], order=0, titanic, weight="Freq") +
    237 |   scale_fill_manual(values=cols, guide="none") +
    238 |   scale_colour_manual(values=cols, guide="none") + theme_bw()
    239 | 
    240 | ## hammock plot with same width lines
    241 | ggparallel(names(titanic)[c(1,4,2,3)], titanic, weight=1, asp=0.5,
    242 |            method="hammock", ratio=0.2, order=c(0,0)) +
    243 | theme( legend.position="none") +
    244 | scale_fill_brewer(palette="Paired") +
    245 | scale_colour_brewer(palette="Paired")
    246 | 
    247 | ## hammock plot with line widths adjusted by frequency
    248 | ggparallel(names(titanic)[c(1,4,2,3)], titanic, weight="Freq",
    249 |            asp=0.5, method="hammock", order=c(0,0), text.angle=0,
    250 |            width=0.45) +
    251 |   theme( legend.position="none")
    252 | 
    253 | 
    254 | ## biological examples: genes and pathways
    255 | data(genes)
    256 | cols <- c(rep("grey80", 24), brewer.pal("YlOrRd", n = 9))
    257 | genes$chrom <- factor(genes$chrom, levels=c(paste("chr", 1:22, sep=""), "chrX", "chrY"))
    258 | ggparallel(list("path", "chrom"), text.offset=c(0.03, 0,-0.03),
    259 |            data = genes,  width=0.1, order=c(1,0), text.angle=0,
    260 |            color="white",
    261 |    factorlevels =  c(sapply(unique(genes$chrom), as.character),
    262 |      unique(genes$path))) +
    263 |    scale_fill_manual(values = cols, guide="none") +
    264 |    scale_colour_manual(values = cols, guide="none") +
    265 |    coord_flip()
    266 | }
    267 | 
    268 | data(Titanic)
    269 | titanic <- as.data.frame(Titanic)
    270 | 
    271 | titanic$SexSurvived <- with(titanic, interaction(Sex, Survived))
    272 | titanic$SexClassSurvived <- with(titanic, interaction(Sex,Class, Survived))
    273 | 
    274 | ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"), weight="Freq", data=titanic) +
    275 |   theme(legend.position="none") +
    276 |   scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) +
    277 |   scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14))
    278 | 
    279 | 
    280 | ###########
    281 | 
    282 | p1 <- ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"),
    283 |                  weight="Freq", data=titanic, label = FALSE) +
    284 |   theme(legend.position="none") +
    285 |   scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) +
    286 |   scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14))
    287 | p2 <- ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"),
    288 |                  weight="Freq", data=titanic, label = TRUE) +
    289 |   theme(legend.position="none") +
    290 |   scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) +
    291 |   scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14))
    292 | 
    293 | ggplot_build(p2)$data[[4]]
    294 | #>       x       y           label PANEL group colour size angle hjust vjust alpha
    295 | #> 1  1.01  355.49             Yes     1    -1 grey90    4    90   0.5   0.5    NA
    296 | #> 2  1.01 1455.99              No     1    -1 grey90    4    90   0.5   0.5    NA
    297 | #> 3  2.01   62.99       Female.No     1    -1 grey90    4    90   0.5   0.5    NA
    298 | #> 4  2.01  297.99      Female.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    299 | #> 5  2.01  653.49        Male.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    300 | #> 6  2.01 1518.99         Male.No     1    -1 grey90    4    90   0.5   0.5    NA
    301 | #> 7  3.01    1.49  Female.Crew.No     1    -1 grey90    4    90   0.5   0.5    NA
    302 | #> 8  3.01    4.99   Female.1st.No     1    -1 grey90    4    90   0.5   0.5    NA
    303 | #> 9  3.01   13.49   Female.2nd.No     1    -1 grey90    4    90   0.5   0.5    NA
    304 | #> 10 3.01   29.99 Female.Crew.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    305 | #> 11 3.01   52.49    Male.2nd.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    306 | #> 12 3.01   95.99    Male.1st.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    307 | #> 13 3.01  170.99    Male.3rd.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    308 | #> 14 3.01  259.99  Female.3rd.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    309 | #> 15 3.01  351.49  Female.2nd.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    310 | #> 16 3.01  450.99   Female.3rd.No     1    -1 grey90    4    90   0.5   0.5    NA
    311 | #> 17 3.01  562.99     Male.1st.No     1    -1 grey90    4    90   0.5   0.5    NA
    312 | #> 18 3.01  692.49  Female.1st.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    313 | #> 19 3.01  839.99     Male.2nd.No     1    -1 grey90    4    90   0.5   0.5    NA
    314 | #> 20 3.01 1012.99   Male.Crew.Yes     1    -1 grey90    4    90   0.5   0.5    NA
    315 | #> 21 3.01 1319.99     Male.3rd.No     1    -1 grey90    4    90   0.5   0.5    NA
    316 | #> 22 3.01 1865.99    Male.Crew.No     1    -1 grey90    4    90   0.5   0.5    NA
    317 | #>    family fontface lineheight
    318 | #> 1                1        1.2
    319 | #> 2                1        1.2
    320 | #> 3                1        1.2
    321 | #> 4                1        1.2
    322 | #> 5                1        1.2
    323 | #> 6                1        1.2
    324 | #> 7                1        1.2
    325 | #> 8                1        1.2
    326 | #> 9                1        1.2
    327 | #> 10               1        1.2
    328 | #> 11               1        1.2
    329 | #> 12               1        1.2
    330 | #> 13               1        1.2
    331 | #> 14               1        1.2
    332 | #> 15               1        1.2
    333 | #> 16               1        1.2
    334 | #> 17               1        1.2
    335 | #> 18               1        1.2
    336 | #> 19               1        1.2
    337 | #> 20               1        1.2
    338 | #> 21               1        1.2
    339 | #> 22               1        1.2
    340 | p1 + geom_text(aes(x = x, y=y, label = label), data = ggplot_build(p2)$data[[4]])
    341 | 
    342 | 
    343 |
    344 |
    346 | 347 | 348 |
    351 | 352 | 355 | 356 |
    357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | Function reference • ggparallel 6 | Skip to contents 7 | 8 | 9 |
    41 |
    42 |
    45 | 46 |
    47 |

    All functions

    48 | 49 | 50 | 51 | 52 |
    53 | 54 | 55 | 56 | 57 |
    58 | 59 | genes 60 |
    61 |
    Data linking genes and pathways.
    62 |
    63 | 64 | ggparallel() 65 |
    66 |
    Variations of parallel coordinate plots
    67 |
    68 | 69 | package-ggparallel 70 |
    71 |
    A package for creating parallel coordinates for categorical data
    72 |
    73 |
    74 | 75 | 76 |
    79 | 80 | 83 | 84 |
    85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/reference/package-ggparallel.html: -------------------------------------------------------------------------------- 1 | 2 | A package for creating parallel coordinates for categorical data — package-ggparallel • ggparallel 10 | Skip to contents 11 | 12 | 13 |
    45 |
    46 |
    51 | 52 |
    53 |

    The main function ggparallel implements three types of 54 | parallel coordinate plots for categorical data: hammock plots, parallel 55 | sets plots, and common angle plots.

    56 |
    57 | 58 | 59 | 60 |
    61 | 62 | 63 |
    66 | 67 | 70 | 71 |
    72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://heike.github.io/ggparallel/404.html 5 | 6 | 7 | https://heike.github.io/ggparallel/LICENSE-text.html 8 | 9 | 10 | https://heike.github.io/ggparallel/authors.html 11 | 12 | 13 | https://heike.github.io/ggparallel/index.html 14 | 15 | 16 | https://heike.github.io/ggparallel/news/index.html 17 | 18 | 19 | https://heike.github.io/ggparallel/reference/genes.html 20 | 21 | 22 | https://heike.github.io/ggparallel/reference/ggparallel.html 23 | 24 | 25 | https://heike.github.io/ggparallel/reference/index.html 26 | 27 | 28 | https://heike.github.io/ggparallel/reference/package-ggparallel.html 29 | 30 | 31 | -------------------------------------------------------------------------------- /ggparallel.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry( 2 | bibtype = "Article", 3 | title = "Common Angle Plots as Perception-True Visualizations of Categorical Associations", 4 | author = "Heike Hofmann and Marie Vendettuoli", 5 | journal = "IEEE Transactions on Visualization & Computer Graphics", 6 | year = "2013", 7 | volume = "", 8 | number = "12", 9 | pages = "2297--2305", 10 | doi = "10.1109/TVCG.2013.140" 11 | ) 12 | -------------------------------------------------------------------------------- /inst/examples/ggparallel-ex.R: -------------------------------------------------------------------------------- 1 | data(mtcars) 2 | 3 | ggparallel(list("gear", "cyl"), data=mtcars) 4 | ggparallel(list("gear", "cyl"), data=mtcars, method="hammock", ratio=0.25) 5 | 6 | require(RColorBrewer) 7 | require(ggplot2) 8 | cols <- c(brewer.pal(4, "Reds")[-1], brewer.pal(4, "Blues")[-1]) 9 | ggparallel(list("gear", "cyl"), ratio=0.2, data=mtcars, 10 | method="hammock", text.angle=0) + 11 | scale_fill_manual(values=cols) + scale_colour_manual(values=cols) + 12 | theme_bw() 13 | 14 | ## combination of common angle plot and hammock adjustment: 15 | ggparallel(list("gear", "cyl"), data=mtcars, method="adj.angle", 16 | ratio=2) 17 | 18 | ## compare with method='parset' 19 | ggparallel(list("gear", "cyl"), data=mtcars, method='parset') 20 | 21 | ## flip plot and rotate text 22 | ggparallel(list("gear", "cyl"), data=mtcars, text.angle=0) + 23 | coord_flip() 24 | 25 | ## change colour scheme 26 | ggparallel(list("gear", "cyl"), data=mtcars, text.angle=0) + 27 | coord_flip() + 28 | scale_fill_brewer(palette="Set1") + 29 | scale_colour_brewer(palette="Set1") 30 | 31 | ## example with more than two variables: 32 | titanic <- as.data.frame(Titanic) 33 | ggparallel(names(titanic)[c(1,4,2,1)], order=0, titanic, weight="Freq") + 34 | scale_fill_brewer(palette="Paired", guide="none") + 35 | scale_colour_brewer(palette="Paired", guide="none") 36 | 37 | \dontrun{ 38 | cols <- c(brewer.pal(5,"Blues")[-1], brewer.pal(3, "Oranges")[-1], 39 | brewer.pal(3, "Greens")[-1]) 40 | ggparallel(names(titanic)[c(1,4,2,1)], order=0, titanic, weight="Freq") + 41 | scale_fill_manual(values=cols, guide="none") + 42 | scale_colour_manual(values=cols, guide="none") + theme_bw() 43 | 44 | ## hammock plot with same width lines 45 | ggparallel(names(titanic)[c(1,4,2,3)], titanic, weight=1, asp=0.5, 46 | method="hammock", ratio=0.2, order=c(0,0)) + 47 | theme( legend.position="none") + 48 | scale_fill_brewer(palette="Paired") + 49 | scale_colour_brewer(palette="Paired") 50 | 51 | ## hammock plot with line widths adjusted by frequency 52 | ggparallel(names(titanic)[c(1,4,2,3)], titanic, weight="Freq", 53 | asp=0.5, method="hammock", order=c(0,0), text.angle=0, 54 | width=0.45) + 55 | theme( legend.position="none") 56 | 57 | 58 | ## biological examples: genes and pathways 59 | data(genes) 60 | cols <- c(rep("grey80", 24), brewer.pal("YlOrRd", n = 9)) 61 | genes$chrom <- factor(genes$chrom, levels=c(paste("chr", 1:22, sep=""), "chrX", "chrY")) 62 | ggparallel(list("path", "chrom"), text.offset=c(0.03, 0,-0.03), 63 | data = genes, width=0.1, order=c(1,0), text.angle=0, 64 | color="white", 65 | factorlevels = c(sapply(unique(genes$chrom), as.character), 66 | unique(genes$path))) + 67 | scale_fill_manual(values = cols, guide="none") + 68 | scale_colour_manual(values = cols, guide="none") + 69 | coord_flip() 70 | } 71 | 72 | data(Titanic) 73 | titanic <- as.data.frame(Titanic) 74 | 75 | titanic$SexSurvived <- with(titanic, interaction(Sex, Survived)) 76 | titanic$SexClassSurvived <- with(titanic, interaction(Sex,Class, Survived)) 77 | 78 | ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"), weight="Freq", data=titanic) + 79 | theme(legend.position="none") + 80 | scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) + 81 | scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14)) 82 | 83 | ########### 84 | 85 | p1 <- ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"), 86 | weight="Freq", data=titanic, label = FALSE) + 87 | theme(legend.position="none") + 88 | scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) + 89 | scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14)) 90 | p2 <- ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"), 91 | weight="Freq", data=titanic, label = TRUE) + 92 | theme(legend.position="none") + 93 | scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) + 94 | scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14)) 95 | 96 | ggplot_build(p2)$data[[4]] 97 | p1 + geom_text(aes(x = x, y=y, label = label), data = ggplot_build(p2)$data[[4]]) 98 | -------------------------------------------------------------------------------- /inst/mtcars.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/inst/mtcars.rda -------------------------------------------------------------------------------- /inst/references.bib: -------------------------------------------------------------------------------- 1 | @article{jen2, 2 | title={Water In, Water Out}, 3 | author={Mark Fischetti}, 4 | year = {June 2012}, 5 | journal={Scientific American} 6 | } 7 | 8 | @article{jen1, 9 | title={Global Demand Stresses Limited Supply}, 10 | author={Mark Fischetti}, 11 | year = {October 2011}, 12 | journal={Scientific American} 13 | } 14 | 15 | @article{schmidt:2008, 16 | author={Mario Schmidt}, 17 | title={The {S}ankey Diagram in Energy and Material Flow Management}, 18 | journal={Journal of Industrial Ecology}, 19 | number={12}, 20 | pages={173--185}, 21 | doi={10.1111/j.1530-9290.2008.00015.x}, 22 | year={2008} 23 | } 24 | 25 | @misc{minard:1812, 26 | author={Charles Minard}, 27 | title={Carte figurative des pertes successives en hommes de l'{A}rm\'ee {F}ran\c{c}aise dans la campagne de {R}ussie 1812-1813}, 28 | publisher={Regnier et Dourdet, Paris}, 29 | year={1869}, 30 | comment={The aim of my carte figurative is less to express statistical results, better done by numbers, than to convey promptly to the eye the relation not given quickly by numbers requiring mental calculation} 31 | } 32 | 33 | @misc{sankey:1898, 34 | author={Henry Riall Sankey}, 35 | title={Introductory Note on the Thermal Efficiency of Steam-Engines}, 36 | howpublished={Report of the Committee appointed on the 31st March, 1896, to Consider and Report to the Council upon the Subject of the Definition of a Standard or Stan- dards of Thermal Efficiency for Steam-Engines: with an Introductory Note. Minutes of Proceedings of The Institution of Civil Engineers}, 37 | number={134}, 38 | year={1898}, 39 | pages={278--283} 40 | } 41 | 42 | 43 | @article{day:1991, 44 | author={Ross H Day and Erica J Stecher}, 45 | year={1991}, 46 | journal={Perception}, 47 | title={Sine of an illusion}, 48 | volume={20}, 49 | pages={49--55} 50 | } 51 | 52 | 53 | @Misc{bach, 54 | author={Michael Bach}, 55 | title={Visual Phenomena \& Optical Illusions}, 56 | url={http://www.michaelbach.de/ot/} 57 | } 58 | 59 | @Book{ggplot2, 60 | author = {Hadley Wickham}, 61 | title = {ggplot2: elegant graphics for data analysis}, 62 | publisher = {Springer New York}, 63 | year = {2009}, 64 | isbn = {978-0-387-98140-6}, 65 | url = {http://had.co.nz/ggplot2/book}, 66 | } 67 | @Manual{R, 68 | title = {R: A Language and Environment for Statistical Computing}, 69 | author = {{R Core Team}}, 70 | organization = {R Foundation for Statistical Computing}, 71 | address = {Vienna, Austria}, 72 | year = {2012}, 73 | note = {{ISBN} 3-900051-07-0}, 74 | url = {http://www.R-project.org/}, 75 | } 76 | 77 | @misc{pcp:1885, 78 | author={Maurice d'Ocagne}, 79 | title={Coordonn\'ees parall\`eles et axiales : M\'ethode de transformation g\'eom\'etrique et proc\'ed\'e nouveau de calcul graphique déduits de la consid\'eration des coordonn\'ees parall\`eles}, 80 | address={Paris}, 81 | howpublished={Gauthier-Villars}, 82 | year=1885 83 | } 84 | @article{inselberg:1985, 85 | author={Alfred Inselberg}, 86 | title={The Plane with Parallel Coordinates}, 87 | year={1985}, 88 | journal={The Visual Computer}, 89 | number={2}, 90 | volume={1}, 91 | pages={69--91} 92 | } 93 | @article{wegman:1990, 94 | jstor_articletype = {research-article}, 95 | title = {Hyperdimensional Data Analysis Using Parallel Coordinates}, 96 | author = {Wegman, Edward J.}, 97 | journal = {Journal of the American Statistical Association}, 98 | jstor_issuetitle = {}, 99 | volume = {85}, 100 | number = {411}, 101 | jstor_formatteddate = {Sep., 1990}, 102 | pages = {pp. 664-675}, 103 | url = {http://www.jstor.org/stable/2290001}, 104 | ISSN = {01621459}, 105 | abstract = {This article presents the basic results of using the parallel coordinate representation as a high-dimensional data analysis tool. Several alternatives are reviewed. The basic algorithm for parallel coordinates is laid out and a discussion of its properties as a projective transformation is given. Several duality results are discussed along with their interpretations as data analysis tools. Permutations of the parallel coordinate axes are discussed, and some examples are given. Some extensions of the parallel coordinate idea are given. The article closes with a discussion of implementation and some of my experiences.}, 106 | language = {English}, 107 | year = {1990}, 108 | publisher = {American Statistical Association}, 109 | copyright = {Copyright © 1990 American Statistical Association}, 110 | } 111 | 112 | @article{cleveland:1984, 113 | jstor_articletype = {research-article}, 114 | title = {Graphical Perception: Theory, Experimentation, and Application to the Development of Graphical Methods}, 115 | author = {Cleveland, William S. and McGill, Robert}, 116 | journal = {Journal of the American Statistical Association}, 117 | jstor_issuetitle = {}, 118 | volume = {79}, 119 | number = {387}, 120 | jstor_formatteddate = {Sep., 1984}, 121 | pages = {pp. 531-554}, 122 | url = {http://www.jstor.org/stable/2288400}, 123 | ISSN = {01621459}, 124 | abstract = {The subject of graphical methods for data analysis and for data presentation needs a scientific foundation. In this article we take a few steps in the direction of establishing such a foundation. Our approach is based on graphical perception-the visual decoding of information encoded on graphs-and it includes both theory and experimentation to test the theory. The theory deals with a small but important piece of the whole process of graphical perception. The first part is an identification of a set of elementary perceptual tasks that are carried out when people extract quantitative information from graphs. The second part is an ordering of the tasks on the basis of how accurately people perform them. Elements of the theory are tested by experimentation in which subjects record their judgments of the quantitative information on graphs. The experiments validate these elements but also suggest that the set of elementary tasks should be expanded. The theory provides a guideline for graph construction: Graphs should employ elementary tasks as high in the ordering as possible. This principle is applied to a variety of graphs, including bar charts, divided bar charts, pie charts, and statistical maps with shading. The conclusion is that radical surgery on these popular graphs is needed, and as replacements we offer alternative graphical forms-dot charts, dot charts with grouping, and framed-rectangle charts.}, 125 | language = {English}, 126 | year = {1984}, 127 | publisher = {American Statistical Association}, 128 | copyright = {Copyright © 1984 American Statistical Association}, 129 | } 130 | 131 | @book{wainer:2000, 132 | author={Howard Wainer}, 133 | title={Visual Revelations}, 134 | year={2000}, 135 | publisher={Psychology Press} 136 | } 137 | 138 | @book{robbins:2005, 139 | author={Naomi Robbins}, 140 | title={Creating More Effective Graphs}, 141 | publisher={Wiley}, 142 | year={2005} 143 | } 144 | 145 | @book{playfair2, 146 | author={William Playfair and Howard Wainer and Ian Spence}, 147 | title={Playfair's Commercial and Political Atlas and Statistical Breviary}, 148 | publisher={Cambridge University Press}, 149 | year={2005} 150 | } 151 | 152 | @book{playfair, 153 | author={William Playfair}, 154 | year={1786}, 155 | title={Commercial and Political Atlas}, 156 | address={London} 157 | } 158 | 159 | @article{kosara:2006, 160 | author = {Kosara, Robert and Bendix, Fabian and Hauser, Helwig}, 161 | title = {Parallel Sets: Interactive Exploration and Visual Analysis of Categorical Data}, 162 | journal = {IEEE Transactions on Visualization and Computer Graphics}, 163 | issue_date = {July 2006}, 164 | volume = {12}, 165 | number = {4}, 166 | month = jul, 167 | year = {2006}, 168 | issn = {1077-2626}, 169 | pages = {558--568}, 170 | numpages = {11}, 171 | url = {http://dx.doi.org/10.1109/TVCG.2006.76}, 172 | doi = {10.1109/TVCG.2006.76}, 173 | acmid = {1137510}, 174 | publisher = {IEEE Educational Activities Department}, 175 | address = {Piscataway, NJ, USA}, 176 | keywords = {Information visualization, Information visualization, interaction, nominal data, categorical data, multivariate data., categorical data, interaction, multivariate data., nominal data}, 177 | } 178 | 179 | @Misc{bbc:2009, 180 | author={Michael Blastland}, 181 | title={Go Figure: How to understand risk in 13 clicks}, 182 | journal={BBC Magazine}, 183 | year={March 11 2009}, 184 | url={http://news.bbc.co.uk/2/hi/uk{\_}news/magazine/7937382.stm} 185 | } 186 | 187 | @inproceedings{schonlau:2003, 188 | Author = {Matthias Schonlau}, 189 | Booktitle = {Proceedings of the Section on Statistical Graphics}, 190 | Date-Added = {2012-04-18 16:10:00 -0500}, 191 | Date-Modified = {2012-04-18 16:12:08 -0500}, 192 | Organization = {RAND Corporation}, 193 | Publisher = {American Statistical Association}, 194 | Title = {Visualizing Categorical Data Arising in the Health Sciences Using Hammock Plots}, 195 | Year = {2003}} 196 | 197 | @article{dawson:1995, 198 | author={Robert J. Dawson}, 199 | year={1995}, 200 | title={The `Unusual Episode’ Data Revisited.}, 201 | journal={Journal of Statistics Education}, 202 | volume={3}, 203 | url={http://www.amstat.org/publications/jse/v3n3/datasets.dawson.html} 204 | } 205 | 206 | -------------------------------------------------------------------------------- /inst/titanic_adjangle.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/inst/titanic_adjangle.rda -------------------------------------------------------------------------------- /inst/titanic_hammock.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/inst/titanic_hammock.rda -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/man/figures/README-unnamed-chunk-2-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heike/ggparallel/20a04c1cb3f95b9e570e7eea781e50b59597d534/man/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /man/genes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/genes.R 3 | \docType{data} 4 | \name{genes} 5 | \alias{genes} 6 | \title{Data linking genes and pathways.} 7 | \format{ 8 | An object of class \code{data.frame} with 2768 rows and 14 columns. 9 | } 10 | \usage{ 11 | genes 12 | } 13 | \description{ 14 | Table knownGene from track UCSC Genes was downloaded from the UCSC table 15 | browser for the human genome assembly (hg18, May 2006) and filtered for a 16 | selection of pathways associated with human metabolism was obtained from KEGG 17 | PATHWAY database. Bioconductor package KEGG.db was used to provide mappings 18 | between gene and pathway identifiers. 19 | } 20 | \examples{ 21 | library(ggplot2) 22 | library(RColorBrewer) 23 | genes$chrom <- factor(genes$chrom, levels=c(paste("chr", 1:22, sep=""), 24 | "chrX", "chrY")) 25 | ggparallel( 26 | list("path", "chrom"), 27 | text.offset = c(0.03, 0,-0.03), 28 | data = genes, 29 | width = 0.1, 30 | order = c(1, 0), 31 | angle = 0, 32 | color = "white", 33 | factorlevels = c(sapply(unique(genes$chrom), as.character),unique(genes$path)) 34 | ) + 35 | scale_fill_manual( 36 | values = c(brewer.pal("YlOrRd", n = 9), rep("grey80", 24)), 37 | guide = "none" 38 | ) + 39 | scale_colour_manual( 40 | values = c(brewer.pal("YlOrRd", n = 9), rep("grey80", 24)), 41 | guide = "none" 42 | ) + 43 | coord_flip() 44 | } 45 | \references{ 46 | Fujita PA, Rhead B, Zweig AS, Hinrichs AS, Karolchik D, Cline MS, 47 | Goldman M, Barber GP, Clawson H, Coelho A, Diekhans M, Dreszer TR, Giardine 48 | BM, Harte RA, Hillman-Jackson J, Hsu F, Kirkup V, Kuhn RM, Learned K, Li CH, 49 | Meyer LR, Pohl A, Raney BJ, Rosenbloom KR, Smith KE, Haussler D, Kent WJ. The 50 | UCSC Genome Browser database: update 2011. Nucleic Acids Res. 2010 Oct 18. 51 | \url{http://genome.ucsc.edu/index.html?org=Human&db=hg19&hgsid=289810087} 52 | 53 | Marc Carlson, Seth Falcon, Herve Pages and Nianhua Li (). KEGG.db: A set 54 | of annotation maps for KEGG. R package version 2.6.1. 55 | 56 | Kanehisa, M., Goto, S., Sato, Y., Furumichi, M., and Tanabe, M.; KEGG for 57 | integration and interpretation of large-scale molecular datasets. Nucleic 58 | Acids Res. 40, D109-D114 (2012) 59 | 60 | Kanehisa, M. and Goto, S.; KEGG: Kyoto Encyclopedia of Genes and Genomes. 61 | Nucleic Acids Res. 28, 27-30 (2000). 62 | } 63 | \keyword{datasets} 64 | -------------------------------------------------------------------------------- /man/ggparallel.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggparallel.R 3 | \name{ggparallel} 4 | \alias{ggparallel} 5 | \title{Variations of parallel coordinate plots} 6 | \usage{ 7 | ggparallel( 8 | vars = list(), 9 | data, 10 | weight = NULL, 11 | method = "angle", 12 | alpha = 0.5, 13 | width = 0.25, 14 | order = 1, 15 | ratio = NULL, 16 | asp = NULL, 17 | label = TRUE, 18 | label.colour = "grey90", 19 | label.size = 4, 20 | text.angle = 90, 21 | text.offset = NULL, 22 | same.level = FALSE, 23 | ... 24 | ) 25 | } 26 | \arguments{ 27 | \item{vars}{list of variable names to be included in the plotting. Order of 28 | the variables is preserved in the display} 29 | 30 | \item{data}{data frame} 31 | 32 | \item{weight}{weighting variable - use character string} 33 | 34 | \item{method}{plotting method to use - one of \code{angle}, 35 | \code{adj.angle}, \code{parset}, or \code{hammock}, for a hammock plot 36 | the aspect ratio needs to be fixed.} 37 | 38 | \item{alpha}{level of alpha blending for the fill color in ribbons, value 39 | has to be between 0 and 1, defaults to 0.5.} 40 | 41 | \item{width}{width of variables} 42 | 43 | \item{order}{flag variable with three levels -1, 0, 1 for levels in 44 | decreasing order, levels in increasing order and levels unchanged. This 45 | variable can be either a scalar or a vector} 46 | 47 | \item{ratio}{used for methods with angle adjustments (method = 48 | \code{'hammock', 'adj.angle'}): specifies the height (width for horizontal 49 | displays) of the widest line as ratio of the overall display height (width 50 | for horizontal displays).} 51 | 52 | \item{asp}{aspect ratio of the plot - it will be set to a default of 1 in 53 | the case of hammock plots.} 54 | 55 | \item{label}{binary variable (vector), whether labels should be shown.} 56 | 57 | \item{label.colour}{character of colour in which the label should be shown. Ignored, if `label` is FALSE.} 58 | 59 | \item{label.size}{numeric value to determine the size in which labels are shown, defaults to 4} 60 | 61 | \item{text.angle}{numeric value to determine the angle under which labels are shown.} 62 | 63 | \item{text.offset}{(vector) of values for offsetting the labels} 64 | 65 | \item{same.level}{are all variables using the same levels? If yes, simplify the labelling} 66 | 67 | \item{...}{passed on directly to all of the ggplot2 commands} 68 | } 69 | \value{ 70 | returns a ggplot2 object that can be plotted directly or used as base 71 | layer for additional modifications. 72 | } 73 | \description{ 74 | \code{\link{ggparallel}} implements and combines different types of parallel 75 | coordinate plots for categorical data: hammock plots, parallel sets plots, 76 | common angle plots, and common angle plots with a hammock-like adjustment 77 | for line widths. 78 | } 79 | \details{ 80 | Parallel sets have been suggested by \cite{kosara:2006} as a visualization 81 | technique to incorporate categorical variables into a parallel coordinate 82 | plot introduced by \cite{wegman:1990} and \cite{inselberg:1985}. The parallel 83 | sets implemented here are reduced to representations of neighboring 84 | two-dimensional relationships only rather than the hierarchical version 85 | originally suggested. 86 | 87 | Both versions, however, show perceptual problems with interpreting line 88 | widths, leading to potentially wrong conclusions about the data. The hammock 89 | display, introduced by \cite{schonlau:2003}, and the common angle plots are 90 | two approaches at fixing this problem: in Hammock plots the linewidth is 91 | adjusted by a factor countering the strength of the illusion, in the common 92 | angle plot all lines are adjusted to show the same angle - making line widths 93 | again comparable across ribbons. 94 | 95 | Additionally, we can also adjust ribbons in the common angle display for the 96 | angle, to make them appear having the same width (or height) across the 97 | display. We refer to this method as \code{adj.angle}. 98 | } 99 | \examples{ 100 | data(mtcars) 101 | 102 | ggparallel(list("gear", "cyl"), data=mtcars) 103 | ggparallel(list("gear", "cyl"), data=mtcars, method="hammock", ratio=0.25) 104 | 105 | require(RColorBrewer) 106 | require(ggplot2) 107 | cols <- c(brewer.pal(4, "Reds")[-1], brewer.pal(4, "Blues")[-1]) 108 | ggparallel(list("gear", "cyl"), ratio=0.2, data=mtcars, 109 | method="hammock", text.angle=0) + 110 | scale_fill_manual(values=cols) + scale_colour_manual(values=cols) + 111 | theme_bw() 112 | 113 | ## combination of common angle plot and hammock adjustment: 114 | ggparallel(list("gear", "cyl"), data=mtcars, method="adj.angle", 115 | ratio=2) 116 | 117 | ## compare with method='parset' 118 | ggparallel(list("gear", "cyl"), data=mtcars, method='parset') 119 | 120 | ## flip plot and rotate text 121 | ggparallel(list("gear", "cyl"), data=mtcars, text.angle=0) + 122 | coord_flip() 123 | 124 | ## change colour scheme 125 | ggparallel(list("gear", "cyl"), data=mtcars, text.angle=0) + 126 | coord_flip() + 127 | scale_fill_brewer(palette="Set1") + 128 | scale_colour_brewer(palette="Set1") 129 | 130 | ## example with more than two variables: 131 | titanic <- as.data.frame(Titanic) 132 | ggparallel(names(titanic)[c(1,4,2,1)], order=0, titanic, weight="Freq") + 133 | scale_fill_brewer(palette="Paired", guide="none") + 134 | scale_colour_brewer(palette="Paired", guide="none") 135 | 136 | \dontrun{ 137 | cols <- c(brewer.pal(5,"Blues")[-1], brewer.pal(3, "Oranges")[-1], 138 | brewer.pal(3, "Greens")[-1]) 139 | ggparallel(names(titanic)[c(1,4,2,1)], order=0, titanic, weight="Freq") + 140 | scale_fill_manual(values=cols, guide="none") + 141 | scale_colour_manual(values=cols, guide="none") + theme_bw() 142 | 143 | ## hammock plot with same width lines 144 | ggparallel(names(titanic)[c(1,4,2,3)], titanic, weight=1, asp=0.5, 145 | method="hammock", ratio=0.2, order=c(0,0)) + 146 | theme( legend.position="none") + 147 | scale_fill_brewer(palette="Paired") + 148 | scale_colour_brewer(palette="Paired") 149 | 150 | ## hammock plot with line widths adjusted by frequency 151 | ggparallel(names(titanic)[c(1,4,2,3)], titanic, weight="Freq", 152 | asp=0.5, method="hammock", order=c(0,0), text.angle=0, 153 | width=0.45) + 154 | theme( legend.position="none") 155 | 156 | 157 | ## biological examples: genes and pathways 158 | data(genes) 159 | cols <- c(rep("grey80", 24), brewer.pal("YlOrRd", n = 9)) 160 | genes$chrom <- factor(genes$chrom, levels=c(paste("chr", 1:22, sep=""), "chrX", "chrY")) 161 | ggparallel(list("path", "chrom"), text.offset=c(0.03, 0,-0.03), 162 | data = genes, width=0.1, order=c(1,0), text.angle=0, 163 | color="white", 164 | factorlevels = c(sapply(unique(genes$chrom), as.character), 165 | unique(genes$path))) + 166 | scale_fill_manual(values = cols, guide="none") + 167 | scale_colour_manual(values = cols, guide="none") + 168 | coord_flip() 169 | } 170 | 171 | data(Titanic) 172 | titanic <- as.data.frame(Titanic) 173 | 174 | titanic$SexSurvived <- with(titanic, interaction(Sex, Survived)) 175 | titanic$SexClassSurvived <- with(titanic, interaction(Sex,Class, Survived)) 176 | 177 | ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"), weight="Freq", data=titanic) + 178 | theme(legend.position="none") + 179 | scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) + 180 | scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14)) 181 | 182 | ########### 183 | 184 | p1 <- ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"), 185 | weight="Freq", data=titanic, label = FALSE) + 186 | theme(legend.position="none") + 187 | scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) + 188 | scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14)) 189 | p2 <- ggparallel(vars=list("Survived", "SexSurvived", "SexClassSurvived"), 190 | weight="Freq", data=titanic, label = TRUE) + 191 | theme(legend.position="none") + 192 | scale_fill_manual(values = rep(c("Orange", "Steelblue"), 14)) + 193 | scale_colour_manual(values = rep(c("Orange", "Steelblue"), 14)) 194 | 195 | ggplot_build(p2)$data[[4]] 196 | p1 + geom_text(aes(x = x, y=y, label = label), data = ggplot_build(p2)$data[[4]]) 197 | } 198 | -------------------------------------------------------------------------------- /man/package-ggparallel.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/help.R 3 | \docType{package} 4 | \name{package-ggparallel} 5 | \alias{package-ggparallel} 6 | \title{A package for creating parallel coordinates for categorical data} 7 | \description{ 8 | The main function \code{\link{ggparallel}} implements three types of 9 | parallel coordinate plots for categorical data: hammock plots, parallel 10 | sets plots, and common angle plots. 11 | } 12 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview 7 | # * https://testthat.r-lib.org/articles/special-files.html 8 | 9 | library(testthat) 10 | library(ggparallel) 11 | 12 | test_check("ggparallel") 13 | -------------------------------------------------------------------------------- /tests/testthat/test-ggparallel.R: -------------------------------------------------------------------------------- 1 | save_png <- function(code, width = 400, height = 400) { 2 | path <- tempfile(fileext = ".png") 3 | png(path, width = width, height = height) 4 | on.exit(dev.off()) 5 | code 6 | 7 | path 8 | } 9 | 10 | test_that("ggparallel works", { 11 | load(system.file("mtcars.rda", package="ggparallel")) # loads object test_mtcars_plot 12 | built_saved <- ggplot2::ggplot_build(test_mtcars_plot) 13 | test <- ggparallel(list("gear", "cyl"), data=mtcars) 14 | build_now <- ggplot2::ggplot_build(test) 15 | # test_mtcars_plot <- test 16 | # save(test_mtcars_plot, file="inst/mtcars.rda") 17 | 18 | # data is the same 19 | expect_equal(built_saved$data, build_now$data, tolerance=1e-4) 20 | 21 | # we have three layers 22 | expect_equal(length(test$layers), 3) 23 | classes <- 24 | c(class(test$layers[[1]]$geom), class(test$layers[[2]]$geom), class(test$layers[[3]]$geom)) 25 | # we have the right layer classes 26 | expect_contains(classes, c("GeomRibbon", "GeomBar", "GeomText")) 27 | 28 | # throw error 29 | expect_message(expect_error(ggparallel(list("gear"), data=mtcars))) 30 | 31 | # hammock plots 32 | load(system.file("titanic_hammock.rda", package="ggparallel")) # loads object titanic_hammock 33 | 34 | titanic <- as.data.frame(Titanic) 35 | titanic_plot <- ggparallel(names(titanic)[c(1,4,2,3)], titanic, weight=1, asp=0.5, 36 | method="hammock", ratio=0.2, order=c(0,0)) 37 | build_now <- ggplot2::ggplot_build(titanic_plot) 38 | # titanic_hammock <- build_now$data 39 | # save(titanic_hammock, file="inst/titanic_hammock.rda") 40 | 41 | expect_equal(titanic_hammock, build_now$data, tolerance=1e-4) 42 | 43 | # adjusted angle 44 | load(system.file("titanic_adjangle.rda", package="ggparallel")) # loads object titanic_adjangle 45 | 46 | titanic <- as.data.frame(Titanic) 47 | titanic_plot <- ggparallel(list("gear", "cyl"), data=mtcars, method="adj.angle", ratio=2.5) 48 | build_now <- ggplot2::ggplot_build(titanic_plot) 49 | # titanic_adjangle <- build_now$data 50 | # save(titanic_adjangle, file="inst/titanic_adjangle.rda") 51 | 52 | expect_equal(titanic_adjangle, build_now$data, tolerance=1e-4) 53 | }) 54 | --------------------------------------------------------------------------------