arrow type FactoMineR - r

I've used the 'PCA' function from the 'FactoMineR' package to obtain principal component scores. I've tried reading through the package details and similar questions on this forum but can't figure out the code to modify the line type of the arrows used to represent supplementary variables on the variables factor map. By default, these are blue and dashed lines and I desperately cannot find how to make them continuous
I don't manage ggplot and really want to know if there is a solution to this kind of plot :
plot(res, choix="var")
Does someone know the tip please ?
For example, here is a code :
library(FactoMineR)
data("decathlon")
res <- PCA(decathlon,quanti.sup = 10:12,quali.sup = 13) #this would generate an automatic plot but I'd prefer working on a personal plot
windows()
plot(res,choix="var", shadow = T, title="", cex = 1.2, cex.lab = 1.3)

The dashed line parameter is hard-coded, so you can't alter it when calling the function. Here is the exact line of code the function is calling:
arrows(0, 0, coord.quanti[q, 1], coord.quanti[q, 2], length = 0.1, angle = 15, code = 2, lty = 2, col=coll2[q])
If you need to change it, you would have to get the code from github and change lty=2 to lty=1 on line 350 (shown above), or just make it an optional input parameter to the function and set lty to the variable value. Then, you would call plot.PCA(res,choix="var", shadow = T, title="", cex = 1.2, cex.lab = 1.3)

Related

R: plot() Function with type="h" Misrepresents Small Numbers ( For Larger Values of "lwd" )

I am trying to generate a plot showing the probabilities of a Binomial(10, 0.3) distribution.
I'd like to do this in base R.
The following code is the best I have come up with,
plot(dbinom(1:10, 10, 0.3), type="h", lend=2, lwd=20, yaxs="i")
My issue with the above code is the small numbers get disproportionately large bars. (See below) For example P(X = 8) = 0.00145 but the height in the plot looks like about 0.025.
It seems to be an artifact created by wanting wider bars, if the lwd = 20 argument is removed you get tiny bars but their heights seem to be representative.
I think the problem is your choice of lend (line-end) parameter. The 'round' (0) and 'square' (2) choices are intended for when you want a little bit of extra extension beyond the end of a segment, e.g. so that adjacent segments join nicely, e.g. if you were plotting line segments that should be part of a connected line (see example below).
f <- function(le) plot(dbinom(1:10, 10, 0.3),
type="h", lend = le, lwd=20, yaxs="i", main = le)
par(mfrow=c(1,3))
invisible(lapply(c("round", "butt", "square"), f))
"round", "butt", and "square" could also be specified (less mnemonically) as 0, 1, and 2 ...
x <- 1:5; y <- c(1,4,2,3,5)
f2 <- function(le) {
plot(x,y, type ="n", main = le)
segments(x[-length(x)], y[-length(x)], x[-1], y[-1],
lwd = 20, lend = le)
}
par(mfrow=c(1,3))
invisible(lapply(c("round", "butt", "square"), f2))
Here you can see that the round end caps work well, both 'butt' and 'square' have issues. (I can't think offhand of a use case for "square", but I'm sure one exists ...) There is a good description of line-drawing parameters here (although it also doesn't suggest use cases ...)

plot function in R producing legend without legend() being called

I'm trying to produce a cumulative incidence plot for a competing hazards survival analysis using plot() in R. For some reason, the plot that is produced has a legend that I have not called. The legend is intersecting with the lines on my graph and I can't figure out how to get rid of it. Please help!
My code is as follows:
CompRisk2 <- cuminc(ftime=ADI$time_DeathTxCensor, fstatus=ADI$status, group=ADI$natADI_quart)
cols <- c("darkorange","coral1","firebrick1","firebrick4","lightskyblue","darkturquoise","dodgerblue","dodgerblue4")
par(bg="white")
plot(CompRisk2,
col=cols,
xlab="Years",
ylab="Probability of Mortality or Transplant",
xlim=c(0,10),
ylim=c(0,0.6))
Which produces the following plot:
I tried adding the following code to move the legend out of the frame, but I got an error:
legend(0,5, legend=c(11,21,31,41,12,22,32,42),
col=c("darkorange","coral1","firebrick1","firebrick4","lightskyblue","darkturquoise","dodgerblue","dodgerblue4"),
lty=1:2, cex=0.8, text.font=4, box.lty=0)
Error: Error in title(...) : invalid graphics parameter
Any help would be much appreciated!
You are using the cuminc function from the cmprsk package. This produces an object of class cuminc, which has an S3 plot method. ?plot.cuminc shows you the documentation and typing plot.cuminc shows you the code.
There is some slightly obscure code that suggests a workaround:
u <- list(...)
if (length(u) > 0) {
i <- pmatch(names(u), names(formals(legend)), 0)
do.call("legend", c(list(x = wh[1], y = wh[2], legend = curvlab,
col = color, lty = lty, lwd = lwd, bty = "n", bg = -999999),
u[i > 0]))
}
This says that any additional arguments passed in ... whose names match the names of arguments to legend will be passed to legend(). legend() has a plot argument:
plot: logical. If ‘FALSE’, nothing is plotted but the sizes are returned.
So it looks like adding plot=FALSE to your plot() command will work.
In principle you could try looking at the other arguments to legend() and see if any of them will adjust the legend position/size as you want. Unfortunately the x argument to legend (which would determine the horizontal position) is masked by the first argument to plot.cuminc.
I don't think that the ellipsis arguments are intended for the legend call inside plot.cuminc. The code offered in Ben's answer suggests that there might be a wh argument that determines the location of the legend. It is not named within the parameters as "x" in the code he offered, but is rather given as a positionally-defined argument. If you look at the plot.cuminc function you do in fact find that wh is documented.
I cannot test this because you have not offered us access to the ADI-object but my suggestion would be to try:
opar <- par(xpd=TRUE) # xpd lets graphics be placed 'outside'
plot(CompRisk2,
col=cols, wh=c(-.5, 7),
xlab="Years",
ylab="Probability of Mortality or Transplant",
xlim=c(0,10),
ylim=c(0,0.6))
par(opar) # restores original graphics parameters
It's always a bit risky to put out a code chunk without testing, but I'm happy to report that I did find a suitable test and it seems to work reasonably as predicted. Using the code below on the object in the SO question prior question about using the gg-packages for cmprsk:
library(cmprsk)
# some simulated data to get started
comp.risk.data <- data.frame("tfs.days" = rweibull(n = 100, shape = 1, scale = 1)*100,
"status.tfs" = c(sample(c(0,1,1,1,1,2), size=50, replace=T)),
"Typing" = sample(c("A","B","C","D"), size=50, replace=T))
# fitting a competing risks model
CR <- cuminc(ftime = comp.risk.data$tfs.days,
fstatus = comp.risk.data$status.tfs,
cencode = 0,
group = comp.risk.data$Typing)
opar <- par(xpd=TRUE) # xpd lets graphics be placed 'outside'
plot(CR,
wh=c(-15, 1.1), # obviously different than the OP's coordinates
xlab="Years",
ylab="Probability of Mortality or Transplant",
xlim=c(0,400),
ylim=c(0,1))
par(opar) # restores graphics parameters
I get the legend to move up and leftward from its original position.

Control plot layout in foodweb plot from mvbutils R-package

I would like to visualize how functions in my own R package depend on each other. For this purpose I use the foodweb() function from the mvbutils package.
I can get the right functional dependencies out without a problem but the plot looks a bit messy, with lines crossing each other and function names not aligned vertically or horizontally.
Is there a way to control the layout of the plot similar to the way this works in the igraph package?
Example
dirPath <- "~/dev/stackoverflow/46910042"
setwd(dirPath)
## Download example Package
urlPackage <- "https://github.com/kbroman/qtlcharts/archive/master.zip"
download.file(urlPackage, destfile = "master.zip")
unzip("./master.zip", exdir = dirPath, overwrite = TRUE)
## Install or load mcbutils
if (!require(mvbutils)) install.packages("mvbutils")
thefiles = list.files(path = "./qtlcharts-master/R/", full.names = TRUE)
thefiles
## Now we load all the package files into memory, so we can have
## foodweb generate a map of the package functions.
sapply(thefiles, source)
## Generate plot
par(mar = rep(0.1, 4))
foodweb(border = TRUE, boxcolor = "pink", lwd = 1.5, cex = 0.8)
Plot Output:
Michael,
One option is to look behind the curtains of foodweb. The mvbutils::foodweb function returns an object of (S3) class foodweb. This has three components:
funmat a matrix of 0s and 1s showing what (row) calls what (column). The dimnames are the function names.
x shows the x-axis location of the centre of each function’s name in the display, in par("usr") units
level shows the y-axis location of the centre of each function’s name in the display, in par("usr") units.
thus one approach we can take is to call foodweb but tell it not to create a plot rather return a foodweb object. This then allows us to manipulate the data directory or via graphics::plot() externally of the defaults provided by the mvbutils::foodweb() function.
Why? Well, to do what you suggest my sense is three options exist:
You can either play with mvbutils::foodweb() parameters.
Work with data structure returned with another plotting package.
Use graphics::par() and graphics::plot to manipulate the plot size and attributes of the foodweb structure returned.
It would be great to know your preference. Excluding, that my sense was to provide a base example:
Plot Package Example
In the case of using graphics::plot, you need to go look at how you manipulate graphics:par. par() allows you to set or query graphical parameters. For example, if we want to clean up the function plot you might choose to modify the grahics::par() fin parameter to increase the figure region dimensions, (width, height), in inches. A simple example but my sense it helps map out and demonstrate the options available to you.
## Generate plot
if (!require(qtlcharts)) install.packages("qtlcharts")
## Here we specify `asNamespace` to get the package internals
fw <- foodweb( where = asNamespace( "qtlcharts"),
plotting = FALSE,
)
#Display foodweb structure
str(fw)
# Expand plot figure region dimensions...
par(fin = c(9.9,7))
# Plot fw strucuture
plot(fw,
border = TRUE,
expand.xbox = 1,
boxcolor = "pink", lwd = 1.5, cex = 0.8)
Plot Output example
Note that the function names are not spaced out. Note I cut the top and bottom white of plot here. In this case, you can play with the par constraints such as margin to get the plot you want.
Pruning your plot
Another option within the constraints of mvbutils::foodweb is to use the prune and rprune option to simplify your plots. These are super poweful and useful especially the regular expression version.
if (!require(qtlcharts)) install.packages("qtlcharts")
fw <- foodweb( where = asNamespace( "qtlcharts"),
plotting = FALSE)
str(fw)
par(fin = c(9.9,7))
plot(fw,
border = TRUE,
expand.xbox = 1,
boxcolor = "pink", lwd = 1.5, cex = 0.8)
fw <- foodweb( where = asNamespace( "qtlcharts"),
rprune = "convert_", ## search on `convert_` to negate use `~convert_`
plotting = FALSE)
str(fw)
par(fin = c(9.9,7))
plot(fw,
border = TRUE,
expand.xbox = 1,
boxcolor = "pink", lwd = 1.5, cex = 0.8)
Hoping the above information points you in the right direction.
T.
Because of the fact that there are many data, connections etc, the plot is squeezed in order to fit in the screen, hence it becomes messy.
What I would suggest is to save it in a PDF or PNG with big enough width and Height and then you can zoom in. This will save you a lot of time.
E.G.
## Generate plot
pdf( "mygraph.pdf", width = 50, height = 80 )
par(mar = rep(0.1, 4))
foodweb(border = TRUE, boxcolor = "pink", lwd = 1.5, cex = 0.8)
dev.off()
In addition, you can play with the plot options of foodweb.
Hope it helps.

plot.new has not been called yet when making tiff-file

I am trying to add text (the nonlinearity p-value) to a plot of a restricted cubic spline regression model. When I try this in R studio it works fine, however the moment I try to add code to save it as a .tiff file, I get the following:
Error in strwidth(legend, units = "user", cex = cex, font = text.font) :
plot.new has not been called yet
This is my code (for a restricted cubic spline regression model for the association between determinant labtsh and endpoint ecard with 3 knots):
spline <- cph(Surv(ecard_f,ecard_n)~rcs(labtsh,3)+age+gender+ckdepi+smoking, data=smart)
tiff(file ="H:/documents/test.tiff", width = 1000, height =1000, units = "px", res = 145)
plot(Predict(spline,labtsh,fun=exp), pch = 20, las = 1,
conf.int=T,
main="Relationship TSH and myocardial infarction",
xlab="TSH (mIU/L)",
ylab="Hazard Ratio")
my.p <- anova(spline)[2,3] ##this is the value I want to add in the plot
rp = vector('expression',2)
rp[1] = substitute(expression(Non-linearity))[2]
rp[2] = substitute(expression(italic(p)-value == MYVALUE),
list(MYVALUE = format(my.p, digits = 3)))[2]
legend('topleft', legend = rp, bty = 'n')
dev.off()
Like I said, if I take away the call to make it a .tiff-file and the dev.off() line, the code works fine.
I have searched multiple answers for similar questions here on stackoverflow, but the answers don't seem to help me.

R: PCA plot with different colors for Sites

I´m recently trying to analyse my data and want to make the graphs a little nicer but I´m failing at this.
So I have a data set with 144 sites and 5 environmental variables. It´s basically about the substrate composition around an island and the fish abundance. On this island there is supposed to be a difference in the substrate composition between the north and the southside. Right now I am doing a pca and with the biplot function it works quite fine, but I would like to change the plot a bit.
I need one where the sites are just points and not numbered, arrows point to the different variable and the sites are colored according to their location (north or southside). So I tried everything i could find.
Most examples where with the dune data and suggested something like this:
library(vegan)
library(biplot)
data(dune)
mod <- rda(dune, scale = TRUE)
biplot(mod, scaling = 3, type = c("text", "points"))
So according to this I would just need to say text and points and R would label the variables and just make points for the sites. When i do this, however I get the Error:
Error in plot.default(x, type = "n", xlim = xlim, ylim = ylim, col = col[1L], :
formal argument "type" matched by multiple actual arguments
No idea how to get around this.
So next strategy I found, is to make a plot manually like this:
require("vegan")
data(dune, dune.env)
mod <- rda(dune, scale = TRUE)
scl <- 3 ## scaling == 3
colvec <- c("red2", "green4", "mediumblue")
plot(mod, type = "n", scaling = scl)
with(dune.env, points(mod, display = "sites", col = colvec[Use],
scaling = scl, pch = 21, bg = colvec[Use]))
text(mod,display="species", scaling = scl, cex = 0.8, col = "darkcyan")
with(dune.env, legend("bottomright", legend = levels(Use), bty = "n",
col = colvec, pch = 21, pt.bg = colvec))
This works fine so far as well, I get different colors and points, but now the arrows are missing. So I found that this should be corrected easy, if i just put "display="bp"" in the text line. But this doesn´t work either. Everytime I put "bp" R says:
Error in match.arg(display) :
argument "display" is missing, with no default
So I´m kind of desperate now. I looked through all the answers here and I don´t understand why display="bp" and type=c("text","points") is not working for me.
If anyone has an idea i would be super grateful.
https://www.dropbox.com/sh/y8xzq0bs6mus727/AADmasrXxUp6JTTHN5Gr9eufa?dl=0
This is the link to my dropbox folder. It contains my R-script and the csv files. The one named environmentalvariables_Kon1 also contains the data about north and southside.
So yeah...if anyone could help me. That would be awesome. I really don´t know what to do anymore.
Best regards,
Nancy
You can add arrows with arrows(). See the code for vegan:::biplot.rda to see how it works in the original function.
With your plot, add
g <- scores(mod, display = "species")
len <- 1
arrows(0, 0, len * g[, 1], len * g[, 2], length = 0.05, col = "darkcyan")
You might want to adjust the value of len to make the arrows longer

Resources