#' @eval get_description('scatter_chart')
#' @import struct
#' @export scatter_chart
#' @examples
#' D = iris_DatasetExperiment()
#' C = scatter_chart(
#' xcol = 'Petal.Width',
#' ycol = 'Sepal.Width',
#' factor_name = 'Species'
#' )
#' chart_plot(C,D)
#'
scatter_chart = function(
xcol=1,
ycol=2,
points_to_label='none',
factor_name='none',
ellipse='all',
ellipse_type='norm',
ellipse_confidence=0.95,
label_filter=character(0),
label_factor='rownames',
label_size=3.88,
...) {
out=struct::new_struct('scatter_chart',
xcol=xcol,
ycol=ycol,
points_to_label=points_to_label,
factor_name=factor_name,
ellipse=ellipse,
label_filter=label_filter,
label_factor=label_factor,
label_size=label_size,
ellipse_type=ellipse_type,
ellipse_confidence=ellipse_confidence,
...)
return(out)
}
.scatter_chart<-setClass(
"scatter_chart",
contains='chart',
slots=c(
# INPUTS
xcol='entity',
ycol='entity',
points_to_label='enum',
factor_name='entity',
ellipse='enum',
ellipse_type='enum',
ellipse_confidence='entity',
label_filter='entity',
label_factor='entity',
label_size='entity'
),
prototype = list(name='Group scatter chart',
description='Plots a 2d scatter plot of the input data.',
type="scatter",
.params=c('xcol','ycol','points_to_label','factor_name','ellipse',
'label_filter','label_factor','label_size','ellipse_type',
'ellipse_confidence'),
xcol=entity(
name='x-axis column name',
value=1,
type=c('numeric','integer','character'),
description=paste0('The column name, or index, of data to plot on the x-axis'),
max_length=1
),
ycol=entity(
name='y-axis column name',
value=2,
type=c('numeric','integer','character'),
description=paste0('The column name, or index, of data to plot on the y-axis'),
max_length=1
),
points_to_label=enum(name='Points to label',
value='none',
type='character',
description=c(
'none' = 'No samples labels are displayed.',
"all" = 'The labels for all samples are displayed.',
"outliers" = 'Labels for for potential outlier samples are displayed.'
),
allowed=c('none','all','outliers')
),
factor_name=ents$factor_name,
ellipse=enum(
name = 'Plot ellipses',
description=c(
"all" = paste0('Ellipses are plotted for all groups and all samples.'),
"group" = 'Ellipses are plotted for all groups.',
"none" = 'Ellipses are not included on the plot.',
"sample" = 'An ellipse is plotted for all samples (ignoring group)'),
allowed=c('all','group','none','sample'),
value='all'
),
ellipse_type=enum(
name='Type of ellipse',
description=c(
'norm' = paste0('Multivariate normal (p = 0.95)'),
't' = paste0('Multivariate t (p = 0.95)')
),
value='norm',
type='character',
max_length = 1,
allowed=c('norm','t')
),
ellipse_confidence=entity(
name='Ellipse confidence level',
description='The confidence level for plotting ellipses.',
value=0.95,
type='numeric',
max_length = 1
),
label_filter=entity(
name='Label filter',
value=character(0),
type='character',
description=paste0(
'Labels are only plotted for the named groups. If ',
'zero-length then all groups are included.'
)
),
label_factor=entity(name='Factor for labels',
description=paste0('The column name of sample_meta to use for ',
'labelling samples on the plot. "rownames" will use the row ',
'names from sample_meta.'),
type='character',
value='rownames',
max_length=1),
label_size=entity(name='Text size of labels',
description='The text size of labels. Note this is not in Font Units.',
type='numeric',
value=3.88,
max_length=1)
)
)
#' @importFrom sp point.in.polygon
#' @import ggplot2
#' @importFrom scales squish
#' @export
#' @template chart_plot
setMethod(f="chart_plot",
signature=c("scatter_chart",'DatasetExperiment'),
definition=function(obj,dobj)
{
# if provided convert index to names
if (is.numeric(obj$xcol)) {
obj$xcol=colnames(dobj)[obj$xcol]
}
if (is.numeric(obj$ycol)) {
obj$ycol=colnames(dobj)[obj$ycol]
}
if (obj$points_to_label=='outliers' & !(obj$ellipse %in% c('all','sample'))) {
warning('Outliers are only labelled when plotting the sample ellipse')
}
if (length(obj$factor_name)==1) {
shapes = 19 # filled circles for all samples
} else {
shapes = factor(dobj$sample_meta[[obj$factor_name[2]]])
}
if (obj$label_factor=='rownames') {
slabels = rownames(dobj$sample_meta)
} else {
slabels = dobj$sample_meta[[obj$label_factor]]
}
x=dobj$data[,obj$xcol]
y=dobj$data[,obj$ycol]
xlabel=obj$xcol
ylabel=obj$ycol
# get the factor from meta data
groups=dobj$sample_meta[[obj$factor_name[[1]]]]
# add a space to the front of the labels to offset them from the points, because nudge_x is in data units
for (i in 1:length(slabels)) {
slabels[i]=paste0(' ',slabels[i], ' ')
}
# filter by label_filter list if provided
if (length(obj$label_filter)>0) {
out=!(as.character(groups) %in% obj$label_filter)
slabels[out]=''
}
if (is(groups,'factor') | is(groups,'character')) {
plotClass= createClassAndColors(groups)
groups=plotClass$class
}
# build the plot
A <- data.frame (group=groups,x=x, y=y,slabels=slabels,shape=shapes)
out = ggplot()
# add invisible sample points for ellipse
out = out+geom_point(data=A,aes_string(x='x',y='y'),alpha=0,show.legend=FALSE)
if (length(shapes)>1) {
out=out+geom_point(data=A, aes_(x=~x,y=~y,colour=~group,shape=~shape))
} else {
out=out+geom_point(data=A, aes_(x=~x,y=~y,colour=~group),shape=shapes)
}
out=out+
geom_point(na.rm=TRUE) +
xlab(xlabel) +
ylab(ylabel)
if (length(shapes)>1) {
out=out+labs(shape=obj$factor_name[[2]],colour=obj$factor_name[[1]])
} else {
out=out+labs(color=obj$factor_name[[1]])
}
if (obj$ellipse %in% c('all','group')) {
if (is.factor(groups)) {
out = out +stat_ellipse(data=A, aes_(x=~x,y=~y,colour=~group,group=~group),type=obj$ellipse_type,
level=obj$ellipse_confidence) # ellipse for individual groups
} else {
if (is.factor(shapes)) {
out = out +stat_ellipse(data=A, aes_(x=~x,y=~y,group=~shape),color="#C0C0C0",type=obj$ellipse_type,
level=obj$ellipse_confidence) # ellipse for individual groups
}
}
}
if (is(groups,'factor')) { # if a factor then plot by group using the colours from pmp package
out=out+scale_colour_manual(values=plotClass$manual_colors,
name=obj$factor_name[[1]])
} else {# assume continuous and use the default colour gradient
out=out+scale_colour_viridis_c(limits=quantile(groups,
c(0.05,0.95),na.rm = TRUE),oob=scales::squish,name=obj$factor_name[[1]])
}
out=out+theme_Publication(base_size = 12)
# add ellipse for all samples (ignoring group)
if (obj$ellipse %in% c('all','sample')) {
out=out+stat_ellipse(type=obj$ellipse_type,mapping=aes(x=x,y=y),
colour="#C0C0C0",linetype='dashed',data=A,
level=obj$ellipse_confidence)
}
if (obj$ellipse %in% c('all','sample')) { # only do this if we plotted the sample ellipse
# identify samples outside the ellipse
build=ggplot_build(out)$data
points=build[[1]]
ell=build[[length(build)]]
# outlier for DatasetExperiment ellipse
points$in.ell=as.logical(sp::point.in.polygon(points$x,points$y,ell$x,ell$y))
# label outliers if
if (obj$points_to_label=='outliers')
{
if (!all(points$in.ell))
{
temp=subset(points,!points$in.ell)
temp$group=groups[!points$in.ell]
temp$label=slabels[!points$in.ell]
out=out+geom_text(data=temp,aes_(x=~x,y=~y,label=~label,colour=~group),size=obj$label_size,vjust="inward",hjust="inward",show.legend=FALSE)
}
}
# add a list of outliers to the plot object
out$outliers=trimws(slabels[!points$in.ell])
}
# label all points if requested
if (obj$points_to_label=='all') {
out=out+geom_text(data=A,aes_string(x='x',y='y',colour='group',label='slabels'),vjust="inward",hjust="inward",show.legend=FALSE)
}
return(out)
}
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.