Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
3c71f47
fix some CMD check errors
friendly Sep 4, 2022
38a99da
fix more errors & warnings; use roxygen2 for .Rd
friendly Sep 4, 2022
91dc59d
add varname.color, point.size args
friendly Sep 5, 2022
673e20f
replace plyr w/ dplyr
friendly Jun 29, 2023
e7a60ce
fix undef'd global vars, etc
friendly Jun 29, 2023
d10dc11
fix linewidths; add MF as author
friendly Jun 30, 2023
4396103
make MF maintainer
friendly Jul 1, 2023
87acace
ellipse.size -> ellipse.linewidth
friendly Sep 13, 2023
4d7649d
Added `var.factor` argument
friendly Sep 13, 2023
b8889f9
default ellipse.linewidth=1.3, not NULL
friendly Sep 13, 2023
9b19c4f
add Agashi as contributor
friendly Sep 13, 2023
b540998
change date for win-builder
friendly Sep 13, 2023
694dc9f
add cran-comments
friendly Sep 13, 2023
9cd3a83
Title Case in Title
friendly Sep 13, 2023
ec594e1
add win-builder
friendly Sep 13, 2023
866a3cb
work on README
friendly Sep 14, 2023
af21112
fix ellipse fill problem
friendly Sep 16, 2023
a65e527
add ellipse.fill, ellipse.alpha
friendly Sep 16, 2023
c61fbd3
add hex logo; tweak some ooption defaults
friendly Sep 16, 2023
fbc65cb
add iris example to README
friendly Sep 16, 2023
b1918c7
more testing examples
friendly Sep 16, 2023
76b2976
more testing examples
friendly Sep 16, 2023
874a5ad
fix merge
friendly Sep 16, 2023
36de0fe
add crime data
friendly Sep 17, 2023
bb3484a
add wine variable descriptions
friendly Sep 17, 2023
d04c871
added reflect()
friendly Sep 18, 2023
8c42d1e
added reflect()
friendly Sep 18, 2023
b99319e
conclude merge
friendly Sep 18, 2023
918ece5
re-org examples
friendly Sep 18, 2023
27e4673
fix crime-ex.R
friendly Sep 19, 2023
bd7e9fa
document ggbiplot details; use crime data in README
friendly Sep 19, 2023
0ba237b
add interpretation for crime data to README
friendly Sep 19, 2023
6dd5192
more documentation of ggbiplot.R
friendly Sep 20, 2023
be43cdb
LazyData
friendly Sep 21, 2023
5c720f5
extra/ -> examples; add discussion/
friendly Sep 21, 2023
8ffcaed
add topics/examples for discussion
friendly Sep 21, 2023
891b3fd
update crime docs
friendly Sep 22, 2023
086e5b3
add example to biplotR.Rmd
friendly Sep 22, 2023
c81e6d1
add to discussion/
friendly Sep 28, 2023
85441f3
biplotEX -> biplotEZ
friendly Sep 28, 2023
5b5139f
CARME discussion; doc for ggscreeplot
friendly Nov 28, 2023
3026f01
edit Description: bump date and version
friendly Nov 28, 2023
247126b
update NEWS; spellcheck
friendly Nov 28, 2023
5b97ebc
fix 301 link in ggbiplot.Rd
friendly Nov 28, 2023
84d84df
fix ggbiplot documentation
friendly Dec 3, 2023
58d8395
update README
friendly Dec 4, 2023
ea8023b
check @returns
friendly Dec 5, 2023
94e58ed
tweak README
friendly Dec 5, 2023
aad9ffa
fix point.size buglet in ggbiplot.R
friendly Dec 5, 2023
49556fa
create pkgdown site
friendly Dec 6, 2023
12ca8a9
biplot-packages.xlsx
friendly Dec 11, 2023
368b993
update biplot-packages.Rmd
friendly Dec 11, 2023
8bad4d2
misc changes for submission
friendly Dec 14, 2023
87f0305
tweak NEWS.md
friendly Dec 14, 2023
af4b362
tweak README/rebuild
friendly Dec 14, 2023
bb87cd9
update date field
friendly Dec 15, 2023
b56e0e2
tweak description
friendly Dec 15, 2023
105e63e
tweak description
friendly Dec 15, 2023
623c67b
Merge branch 'master' of github.com:friendly/ggbiplot
friendly Dec 15, 2023
be76d4f
update cran-comments
friendly Dec 15, 2023
121f0e4
update cran-comments
friendly Dec 15, 2023
b71a3cd
pull README.md from devel/
friendly Dec 19, 2023
1c5cb67
re-build site
friendly Dec 19, 2023
34801d9
checkout additions in devel/
friendly Dec 19, 2023
4a7326e
add pkgdown site to DESCRIPTION
friendly Dec 19, 2023
2197d6e
rebuild pkgdown site
friendly Dec 19, 2023
3fef0ff
update ggscreeplot.Rd
friendly Dec 19, 2023
f44866a
Corrected author name, email, and ORCID
vqv Dec 19, 2023
632c898
use get_SVD in ggscreeplot
friendly Dec 22, 2023
c6ed7b4
update README
friendly Dec 22, 2023
4964467
use get_SVD in ggbiplot
friendly Dec 22, 2023
3fdc83e
re-build pkgdown
friendly Dec 22, 2023
70ea1ef
update cran-comments
friendly Dec 31, 2023
af07566
update Date:
friendly Dec 31, 2023
21fa1e5
update Date:
friendly Jan 8, 2024
011746e
fix label spacing; bump pkg version
friendly Apr 24, 2024
64d2479
ggbiplot gains a clip argument
friendly Oct 12, 2024
75f1edc
v0.6.4; add geom.ind
friendly Feb 7, 2025
2c84a8c
implement geom.var
friendly Feb 8, 2025
d447058
test varname folding
friendly Feb 8, 2025
636e2c8
peng-out-test
friendly Feb 15, 2025
a077289
Added lda() objects to those handled by reflect()
friendly Sep 16, 2025
2ef3deb
Illustrate reflection in ggbiplot examples
friendly Sep 16, 2025
1ff9d6b
Merge pull request #5 from friendly/geoms
friendly Sep 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@
^\.Rproj\.user$
^README\.Rmd$
^README-.*\.png$
examples/
discussion/
^cran-comments\.md$
docs/
pkgdown/
_pkgdown.yaml
^CRAN-SUBMISSION$
dev/
48 changes: 34 additions & 14 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
Package: ggbiplot
Type: Package
Title: A ggplot2 based biplot
Version: 0.55
Date: 2011-10-23
Author: Vincent Q. Vu <[email protected]>
Maintainer: Vincent Q. Vu <[email protected]>
Description: A ggplot2 based biplot. It provides a drop-in
replacement for biplot.princomp(). It implements a
biplot and scree plot using ggplot2.
Depends:
ggplot2, plyr, scales, grid
Title: A Grammar of Graphics Implementation of Biplots
Version: 0.6.5
Date: 2025-09-16
Authors@R: c(
person(c("Vincent", "Q."), "Vu", , "[email protected]", role = c("aut"),
comment = c(ORCID = "0000-0002-4689-0497")),
person("Michael", "Friendly", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-3237-0941")),
person("Aghasi", "Tavadyan", , "[email protected]", role = "ctb")
)
Description: A 'ggplot2' based implementation of biplots, giving a representation of a dataset in
a two dimensional space accounting for the greatest variance, together with variable vectors
showing how the data variables relate to this space. It provides a
replacement for stats::biplot(), but with many enhancements to control the analysis and
graphical display. It implements
biplot and scree plot methods which can be used with the results of prcomp(), princomp(),
FactoMineR::PCA(), ade4::dudi.pca() or MASS::lda() and can be customized using 'ggplot2' techniques.
Depends:
R (>= 4.1.0),
ggplot2
Imports:
scales
Suggests:
corrplot,
dplyr,
MASS,
broom,
tidyr
License: GPL-2
URL: http://github.com/vqv/ggbiplot
Collate:
'ggbiplot.r'
'ggscreeplot.r'
Encoding: UTF-8
Language: en-US
URL: https://github.com/friendly/ggbiplot, https://friendly.github.io/ggbiplot/
BugReports: https://github.com/friendly/ggbiplot/issues
RoxygenNote: 7.3.2
LazyData: true
9 changes: 9 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
# Generated by roxygen2: do not edit by hand

export(get_SVD)
export(ggbiplot)
export(ggscreeplot)
export(reflect)
import(ggplot2)
importFrom(scales,muted)
importFrom(stats,predict)
importFrom(stats,qchisq)
importFrom(stats,var)
59 changes: 59 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## Version 0.6.5

- Now Depends R (>= 4.1.0) to handle |>
- Added lda() objects to those handled by reflect()
- Illustrate reflection in ggbiplot examples

## Version 0.6.4

- Documented solution to 'scale_color_discrete() produces two legends' #2
- Fix glitch with axis labels
- `ggbiplot` gains `geom.ind` and `geom.var` arguments for more flexlible handling of the geometries used to display the
observation points and variable labels.

## Version 0.6.3

- Fix axis label spacing
- `ggbiplot` gains a `clip` argument to control if points, labels, etc. are clipped to the axis limits.

## Version 0.6.2

This is a modest upgrade to the initial release, adding a number of features.

- corrected small bugs in `ggbiplot() and `ggscreeplot()`
- `reflect()` now also reflects supplementary variables from `FactoMineR::PCA()`
- added support for `ade4::dudi.pca()`
- `ggbiplot()` gains an `axis.title` argument
- `ggscreeplot()` gains `color`, `shape`, `linetype` and `linewidth` arguments
- Added `get_SVD()` intended the simplify the interface to various PCA functions.
- Now use `get_SVD()` in `ggbiplot()` and `ggscreeplot()`
- Extend some examples, requiring Depends:ggplot2

## Version 0.6.1

- Revised documentation for `ggscreeplot()`
- `data(crime)` used in README giving a more complete example.
- Fixed links reported as 301s
- Published pkgdown site

## Version 0.6.0

- Use `geom_polygon()` rather than `geom_path()` for ellipses to allow them to be filled.
- Added `var.factor` argument to expand or reflect the variable vectors
- Moved points/labels code earlier so ellipses and variable vectors are not obscured
- Replaced internal calculation of ellipses with `stat_ellipse()`
- Now allow ellipses to be filled (`geom_polygon()`) or unfilled (`geom_path()`)
- Added hex logo
- Added iris example to README
- Removed Imports: dplyr, purrr as no longer needed

## Version 0.56

- Fixed many documentation errors and warnings
- Use roxygen2 for documentation
- added `varname.color` to replace fixed `muted("red")`
- tweaked arrow style
- increased default thickness of variable vectors
- add `point.size` argument


53 changes: 53 additions & 0 deletions R/crime.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#' @title U. S. Crimes
#' @name crime
#' @description
#' This dataset gives rates of occurrence (per 100,000 people)
#' various serious crimes in each of the 50 U. S. states,
#' originally from the United States Statistical Abstracts (1970). The data
#' were analyzed by John Hartigan (1975) in his book \emph{Clustering Algorithms} and
#' were later reanalyzed by Friendly (1991).
#'
#' @docType data
#' @usage data(crime)
#' @format
#' A data frame with 50 observations on the following 10 variables.
#' \describe{
#' \item{\code{state}}{state name, a character vector}
#' \item{\code{murder}}{a numeric vector}
#' \item{\code{rape}}{a numeric vector}
#' \item{\code{robbery}}{a numeric vector}
#' \item{\code{assault}}{a numeric vector}
#' \item{\code{burglary}}{a numeric vector}
#' \item{\code{larceny}}{a numeric vector}
#' \item{\code{auto}}{auto thefts, a numeric vector}
#' \item{\code{st}}{state abbreviation, a character vector}
#' \item{\code{region}}{region of the U.S., a factor with levels \code{Northeast} \code{South} \code{North Central} \code{West}}
#' }
#' @keywords dataset
#' @source
#' The data are originally from the United States Statistical Abstracts (1970).
#' This dataset also appears in the SAS/Stat Sample library,
#' \emph{Getting Started Example for PROC PRINCOMP},
#' \url{https://support.sas.com/documentation/onlinedoc/stat/ex_code/131/princgs.html}, from which the
#' current copy was derived.
#' @references
#' Friendly, M. (1991). \emph{SAS System for Statistical Graphics}. SAS Institute.
#'
#' Hartigan, J. A. (1975). \emph{Clustering Algorithms}. John Wiley and Sons.

#' @examples
#' data(crime)
#' library(ggplot2)
#' crime.pca <-
#' crime |>
#' dplyr::select(where(is.numeric)) |>
#' prcomp(scale. = TRUE)
#'
#' ggbiplot(crime.pca,
#' labels = crime$st ,
#' circle = TRUE,
#' varname.size = 4,
#' varname.color = "red") +
#' theme_minimal(base_size = 14)

NULL
72 changes: 72 additions & 0 deletions R/get_SVD.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#' Extract the SVD components from a PCA-like object
#'
#' @description
#'
#' Biplots are based on the Singular Value Decomposition, which for a data matrix is
#' \deqn{\mathbf{X} / \sqrt{n} = \mathbf{U} \mathbf{D} \mathbf{V}^T}
#' but these are computed and returned in quite different
#' forms by various PCA-like methods. This function provides a common interface, returning
#' the components with standard names.
#'
#'
#' @param pcobj an object returned by \code{\link[stats]{prcomp}}, \code{\link[stats]{princomp}},
#' \code{\link[FactoMineR]{PCA}}, \code{\link[ade4]{dudi.pca}}, or \code{\link[MASS]{lda}}
#'
#' @return A list of four elements
#' \describe{
#' \item{n}{The sample size on which the analysis was based}
#' \item{U}{Left singular vectors, giving observation scores}
#' \item{D}{vector of singular values, the diagonal elements of the matrix \eqn{\mathbf{D}}, which are also the square roots
#' of the eigenvalues of \eqn{\mathbf{X} \mathbf{X}'}}
#' \item{V}{Right singular vectors, giving variable loadings}
#' }
#' @export
#'
#' @examples
#' data(crime)
#' crime.pca <-
#' crime |>
#' dplyr::select(where(is.numeric)) |>
#' prcomp(scale. = TRUE)
#'
#' crime.svd <- get_SVD(crime.pca)
#' names(crime.svd)
# # singular values
#' crime.svd$D
#'
get_SVD <- function(pcobj) {

# Recover the SVD from a PCA-like object
if(inherits(pcobj, 'prcomp')){
n <- nrow(pcobj$x)
D <- pcobj$sdev
U <- sweep(pcobj$x, 2, 1 / (D * sqrt(n)), FUN = '*')
V <- pcobj$rotation
} else if(inherits(pcobj, 'princomp')) {
n <- pcobj$n.obs
D <- pcobj$sdev
U <- sweep(pcobj$scores, 2, 1 / (D * sqrt(n)), FUN = '*')
V <- pcobj$loadings
} else if(inherits(pcobj, 'PCA')) {
n <- nrow(pcobj$call$X)
D <- unlist(sqrt(pcobj$eig)[1])
U <- sweep(pcobj$ind$coord, 2, 1 / (D * sqrt(n)), FUN = '*')
V <- sweep(pcobj$var$coord, 2, sqrt(pcobj$eig[1:ncol(pcobj$var$coord),1]), FUN="/")
} else if(inherits(pcobj, "lda")) {
n <- pcobj$N
D <- pcobj$svd
U <- predict(pcobj)$x/sqrt(n)
V <- pcobj$scaling
} else if(inherits(pcobj, 'pca') & inherits(pcobj, 'dudi')){
n <- nrow(pcobj$tab)
D <- sqrt(pcobj$eig)
U <- pcobj$li
V <- pcobj$co
}
else {
stop('Expected a object of class "prcomp", "princomp", "PCA", c("pca", "dudi") or "lda"')
}

list(n=n, U=U, D=D, V=V)

}
Loading