I would like to add line of text under the whole plot. However, it seems ggsurvplot handles plot and risk-table as two entities. I would like to have it like this: enter image description here
However, this is added in MS Word and the journal asks to have it embedded in the picture itself and I am unable to do that.
Thank you :-)
ggsurvplot(fit = fit, data = dat, pval = TRUE,
color = "black",
risk.table = T,
break.time.by = 12,
surv.scale = "percent",
linetype = c("solid","dotted", "dashed"),
legend.labs = c("Control group", "TMA R-ve", "TMA R+ve"),
censor.shape = 124,
legend.title = "",
title = "5-years death-censored graft survival",
xlab = "Months from transplantation",
ylab = "Survival (%)")
I suppose there may be multiple approaches to laying out the plot, table, and text caption. Here is one way I thought might be easier to work with.
The ggsurvplot object, if you include the risk table, will have two ggplot objects contained in it, one for the curve plot, and one for the table (the table itself is a plot).
You can just add to the table plot a caption, and this will appear below the table in the end. If you include hjust = 0 with plot.caption it will be left justified.
Here is an example:
library(survival)
library(survminer)
fit <- survfit(Surv(time, status) ~ sex, data = lung)
ggsurv <- ggsurvplot(fit, risk.table = TRUE)
ggsurv$table <- ggsurv$table +
theme(plot.caption = element_text(hjust = 0)) +
labs(caption = "Figure 1: 5-years death-censored graft survival")
ggsurv
I am trying to rotate labels (not variable names) for a plot I have created, and I am struggling to find and adopt any workable solution. As you can see the labels are not readable I the current form.
Plot is looking into reasons for planning permission objections, and variables are Income, politics, Sex, and Attitude to new homes in their region.
Here is the code. Last iteration, includes labeling function, but does not have any effect on the plot.
library(vcd)
mosaic(~Sex+HomsBultBPV+HHIncQV++PartyID, data=BSA, shade=TRUE,
labeling_args = list(set_varnames = c(Sex="Gender", HomsBultBPV="Attitude To Homes Built in Area",
PartyID="Political Affiliation", HHIncQV="Income Quartile",
labeling= labeling_border(rot_labels = c(25,25,25,0),
just_labels = c("left",
"center",
"center",
"center")))))
The solution is this parameter: "vcd::labeling_border(rot_labels = c(__, __))"
Try out this code:
library(vcd)
mosaic(~ Sex + Age + Survived, data = Titanic,
main = "Survival on the Titanic", shade = TRUE, legend = TRUE,
labeling = vcd::labeling_border(rot_labels = c(45, 45)))
I'm doing some plotting of some mixed models I've been running and am pulling my hair out trying to make sjp.lmer() change the x and y axis labels of a fixed effect. If I'm missing something simple, please let me know!
This is my code:
library(sjPlot);library(lme4)
model = lmer(DV ~ IV + (1|groupingVariable), data = data, REML = F)
sjp.lmer(model,
type = "fe.slope",
vars = c("IV"),
title = "Estimated effect of IV1 on DV",
geom.colors = c("black", "grey49"),
show.ci = T,
axis.title = c("IV Title", "DV Title"))
Model is a formal model estimated using glmer(). The problem is that regardless of what I write, the x and y labels do not change.
I think the syntax is correct, because this code works:
sjp.lmer(model,
type = "re",
sort.est = "sort.all",
facet.grid = F,
axis.title = c("IV Title", "DV Title"))
This second being a plot of the random effects for the same model. Is this a bug? Can you for some reason not specify axis labels for fixed effect models? Thank you!
Seems like a bug. I've raised the issue on gitHub at:
https://github.com/sjPlot/devel/issues/212
As far as I can tell it's just an oversight ("misfeature"/bug). Looking at the code here:
reglinplot <- reglinplot +
labs(title = title,
x = sjmisc::get_label(model_data[[p_v]], def.value = p_v),
y = response)
it seems the labels are hard-coded. Furthermore, the argument list of sjp.reglin (here) doesn't have an axis.title argument ... posting an issue, as you have done, seems like the right way forward.
However, it's not too hard to hack the plot a little bit if you know just a tiny bit about the ggplot2 package.
Set up example:
library(sjPlot); library(lme4
mod <- lmer(Reaction~Days+(Days|Subject),sleepstudy)
p1 <- sjp.lmer(mod,
type = "fe.slope",
vars = "Days") ## stripped-down (warning about colour palette)
Hack labels:
library(ggplot2)
p1$plot.list[[1]] + labs(x="hello",y="goodbye")
The following piece of code produces a trellis dot plot exactly as I would like it, but I would like to automatically add reference lines to the four panels. I have tried searching for examples of code that will let me do this, but so far no luck. Can anyone suggest a simple fix?
dotplot(region ~ productivity | los,
panel = panel.superpose,
group = month,
between = list(x=1, y=0),
index.cond = list(c(4,2,1,3)),
pch = 1:4, col = 1:4,
main = "Monthly Productivity by LoS by Region",
xlab = "Percent",
aspect = 1,
key = list(space = "right",
transparent = TRUE,
points = list(pch = 1:4,
col = 1:4),
text = list(c("Jul", "Aug", "Sep", "Oct"))))
Thanks,
Mike
Depends on where you'd like to have the reference lines. If you need to place them yourself, then use panel.refline(). (It's essentially a wrapper for panel.abline(), replacing that function's default stylings with ones more appropriate for reference lines.)
xyplot(mpg ~ disp, data = mtcars,
panel = function(x,y,...){
panel.refline(h = c(15,17))
panel.xyplot(x,y,...)
})
Alternatively, if you're just wanting a grid of reference lines à la ggplot, the type= argument offers a simple way to get one:
xyplot(mpg ~ disp, data = mtcars, type = c("g", "p")) ## "g"rid and "p"oints
I am trying to visualize my data flow with a Sankey Diagram in R.
I found this blog post linking to an R script that produces a Sankey Diagram; unfortunately, it's quite raw and somewhat limited (see below for sample code and data).
Does anyone know of other scripts—or maybe even a package—that is more developed? My end goal is to visualize both data flow and percentages by relative size of diagram components, like in these examples of Sankey Diagrams.
I posted a somewhat similar question on the r-help list, but after two weeks without any responses I'm trying my luck here on stackoverflow.
Thanks,
Eric
PS. I'm aware of the Parallel Sets Plot, but that is not what I'm looking for.
# thanks to, https://tonybreyal.wordpress.com/2011/11/24/source_https-sourcing-an-r-script-from-github/
sourc.https <- function(url, ...) {
# install and load the RCurl package
if (match('RCurl', nomatch=0, installed.packages()[,1])==0) {
install.packages(c("RCurl"), dependencies = TRUE)
require(RCurl)
} else require(RCurl)
# parse and evaluate each .R script
sapply(c(url, ...), function(u) {
eval(parse(text = getURL(u, followlocation = TRUE,
cainfo = system.file("CurlSSL", "cacert.pem",
package = "RCurl"))), envir = .GlobalEnv)
} )
}
# from https://gist.github.com/1423501
sourc.https("https://raw.github.com/gist/1423501/55b3c6f11e4918cb6264492528b1ad01c429e581/Sankey.R")
# My example (there is another example inside Sankey.R):
inputs = c(6, 144)
losses = c(6,47,14,7, 7, 35, 34)
unit = "n ="
labels = c("Transfers",
"Referrals\n",
"Unable to Engage",
"Consultation only",
"Did not complete the intake",
"Did not engage in Treatment",
"Discontinued Mid-Treatment",
"Completed Treatment",
"Active in \nTreatment")
SankeyR(inputs,losses,unit,labels)
# Clean up my mess
rm("inputs", "labels", "losses", "SankeyR", "sourc.https", "unit")
Sankey Diagram produced with the above code,
This plot can be created through the networkD3 package. It allows you to create interactive sankey diagrams. Here you can find an example. I also added a screenshot so you have an idea what it looks like.
# Load package
library(networkD3)
# Load energy projection data
# Load energy projection data
URL <- paste0(
"https://cdn.rawgit.com/christophergandrud/networkD3/",
"master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)
# Plot
sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
Target = "target", Value = "value", NodeID = "name",
units = "TWh", fontSize = 12, nodeWidth = 30)
I have created a package (riverplot) that has a slightly different, but overlapping functionality compared to the Sankey function, and can produce plots like this one:
If you want to do it with R, your best bid seems to be #Roman suggestion - hack the SankeyR function. For example - below is my very quick fix - simply orient labels verticaly, slighlty offset them and decrease the font for input referals to make it look a bit better. This modification only changes line 171 and 223 in the SankeyR function:
#line171 - change oversized font size of input label
fontsize = max(0.5,frInputs[j]*1.5)#1.5 instead of 2.5
#line223 - srt changes from 35 to 90 to orient labels vertically,
#and offset adjusts them to get better alignment with arrows
text(txtX, txtY, fullLabel, cex=fontsize, pos=4, srt=90, offset=0.1)
I am no ace in trigonometry, but this is really what you need for changing the direction of arrows. That would be ideal in my view - if you could adjust looses arrows so they are oriented horizontally rather then vertically. Otherwise, why my solution fixes the problem with labels orientation, it doesn't make the diagram much more readable...
In addition to rCharts, Sankey diagrams can now be also generated in R with googleVis (version >= 0.5.0). For example, this post describes the generation of the following diagram using googleVis:
R's alluvial package will also do this (from ?alluvial).
# install.packages(c("alluvial"), dependencies = TRUE)
require(alluvial)
# Titanic data
tit <- as.data.frame(Titanic)
# 4d
alluvial( tit[,1:4], freq=tit$Freq, border=NA,
hide = tit$Freq < quantile(tit$Freq, .50),
col=ifelse( tit$Class == "3rd" & tit$Sex == "Male", "red", "gray") )
plotly has the same power as networkD3 package (example link).
For completeness, there is also the ggalluvial package which is a ggplot2 extension for alluvial/Sankey diagrams.
Here is an example taken from the package's documentation
# devtools::install_github("corybrunson/ggalluvial", ref = "optimization")
library(ggalluvial)
titanic_wide <- data.frame(Titanic)
ggplot(data = titanic_wide,
aes(axis1 = Class, axis2 = Sex, axis3 = Age,
y = Freq)) +
scale_x_discrete(limits = c("Class", "Sex", "Age"), expand = c(.1, .05)) +
xlab("Demographic") +
geom_alluvium(aes(fill = Survived)) +
geom_stratum() + geom_text(stat = "stratum", label.strata = TRUE) +
theme_minimal() +
ggtitle("passengers on the maiden voyage of the Titanic",
"stratified by demographics and survival") +
theme(legend.position = 'bottom')
ggplot(titanic_wide,
aes(y = Freq,
axis1 = Survived, axis2 = Sex, axis3 = Class)) +
geom_alluvium(aes(fill = Class),
width = 0, knot.pos = 0, reverse = FALSE) +
guides(fill = FALSE) +
geom_stratum(width = 1/8, reverse = FALSE) +
geom_text(stat = "stratum", label.strata = TRUE, reverse = FALSE) +
scale_x_continuous(expand = c(0, 0),
breaks = 1:3, labels = c("Survived", "Sex", "Class")) +
scale_y_discrete(expand = c(0, 0)) +
coord_flip() +
ggtitle("Titanic survival by class and sex")
Created on 2018-11-13 by the reprex package (v0.2.1.9000)
Judging by these definitions this function, like the Parallel Sets Plot, lacks the capacity to split and combine flows (i.e. through more than one transition).
Since Sankey diagrams are directed weighted graphs, a package like qgraph might be useful.
The SankeyR function provides clearer labels if you sort the losses in descending order as the text is placed closer to the arrow heads without overlapping.
have a look at //sankeybuilder.com as it offers a ready to go solution where you can upload your data and playback variations over time. The transition works well (similar to the youtube demo in your question). If you load the SankeyTrend demo it includes many time slots (Years of data). Once loaded (builds sankeys automatically), click the play button in the upper right hand corner of the page for playback of the time slots, you can even pause and resume time. Demo url is here: SankeyTrend Hope this helps your quest for the perfect Sankey diagram.
Just open sourced a package that uses an alluvial diagram to visualize workflow stages. Since history is kept when the alluvial form is used, there aren't any crossovers in the edges.
https://github.com/claytontstanley/shiny.alluvial