kassambara / survminer Goto Github PK
View Code? Open in Web Editor NEWSurvival Analysis and Visualization
Home Page: https://rpkgs.datanovia.com/survminer/
Survival Analysis and Visualization
Home Page: https://rpkgs.datanovia.com/survminer/
I want to have a 6 by 2 matrix of 12 ggsurvplot
objects. How can this be done? I tried using gridExtra::arrangeGrob()
and gridExtra::marrangeGrob()
without much success.
Thanks!
session_info()
# please paste here the result of
devtools::session_info()
Session info -----------------------------------------------------------------------------------------------------------------------------------------------
setting value
version R version 3.3.1 (2016-06-21)
system x86_64, darwin13.4.0
ui RStudio (0.99.902)
language (EN)
collate en_CA.UTF-8
tz America/Vancouver
date 2016-07-28
Packages ---------------------------------------------------------------------------------------------------------------------------------------------------
package * version date source
assertthat 0.1 2013-12-06 CRAN (R 3.3.0)
biostatUtil * 0.1.0.9050 2016-07-27 local
broom 0.4.1 2016-06-24 CRAN (R 3.3.0)
car 2.1-2 2016-03-25 CRAN (R 3.3.0)
class 7.3-14 2015-08-30 CRAN (R 3.3.1)
codetools 0.2-14 2015-07-15 CRAN (R 3.3.1)
coin 1.1-2 2015-11-16 CRAN (R 3.3.0)
colorspace 1.2-6 2015-03-11 CRAN (R 3.3.0)
DBI 0.4-1 2016-05-08 CRAN (R 3.3.0)
Deducer 0.7-9 2015-12-29 CRAN (R 3.3.0)
devtools 1.12.0 2016-06-24 CRAN (R 3.3.0)
digest 0.6.9 2016-01-08 CRAN (R 3.3.0)
doBy 4.5-15 2016-03-31 CRAN (R 3.3.0)
dplyr * 0.5.0 2016-06-24 CRAN (R 3.3.0)
e1071 1.6-7 2015-08-05 CRAN (R 3.3.0)
effects 3.1-1 2016-03-29 CRAN (R 3.3.0)
foreign 0.8-66 2015-08-19 CRAN (R 3.3.1)
GGally * 1.2.0 2016-07-01 CRAN (R 3.3.0)
ggplot2 * 2.1.0 2016-03-01 CRAN (R 3.3.0)
gridExtra * 2.2.1 2016-02-29 CRAN (R 3.3.0)
gtable 0.2.0 2016-02-26 CRAN (R 3.3.0)
iplots 1.1-7 2013-12-03 CRAN (R 3.3.0)
JavaGD 0.6-1 2012-09-13 CRAN (R 3.3.0)
JGR 1.7-16 2013-12-21 CRAN (R 3.3.0)
KMsurv 0.1-5 2012-12-03 CRAN (R 3.3.0)
labeling 0.3 2014-08-23 CRAN (R 3.3.0)
lattice 0.20-33 2015-07-14 CRAN (R 3.3.1)
lme4 1.1-12 2016-04-16 CRAN (R 3.3.0)
magrittr * 1.5 2014-11-22 CRAN (R 3.3.0)
MASS 7.3-45 2016-04-21 CRAN (R 3.3.1)
Matrix 1.2-6 2016-05-02 CRAN (R 3.3.1)
MatrixModels 0.4-1 2015-08-22 CRAN (R 3.3.0)
memoise 1.0.0 2016-01-29 CRAN (R 3.3.0)
mgcv 1.8-12 2016-03-03 CRAN (R 3.3.1)
minqa 1.2.4 2014-10-09 CRAN (R 3.3.0)
mnormt 1.5-4 2016-03-09 CRAN (R 3.3.0)
modeltools 0.2-21 2013-09-02 CRAN (R 3.3.0)
multcomp 1.4-6 2016-07-14 CRAN (R 3.3.1)
munsell 0.4.3 2016-02-13 CRAN (R 3.3.0)
mvtnorm 1.0-5 2016-02-02 CRAN (R 3.3.0)
nlme 3.1-128 2016-05-10 CRAN (R 3.3.0)
nloptr 1.0.4 2014-08-04 CRAN (R 3.3.0)
nnet 7.3-12 2016-02-02 CRAN (R 3.3.1)
pbkrtest 0.4-6 2016-01-27 CRAN (R 3.3.0)
plyr * 1.8.4 2016-06-08 CRAN (R 3.3.0)
png 0.1-7 2013-12-03 CRAN (R 3.3.0)
psych 1.6.6 2016-06-28 CRAN (R 3.3.0)
quantreg 5.26 2016-06-07 CRAN (R 3.3.0)
R6 2.1.2 2016-01-26 CRAN (R 3.3.0)
Rcpp 0.12.6 2016-07-19 CRAN (R 3.3.1)
reshape 0.8.5 2014-04-23 CRAN (R 3.3.0)
reshape2 1.4.1 2014-12-06 CRAN (R 3.3.0)
rJava 0.9-8 2016-01-07 CRAN (R 3.3.0)
sandwich 2.3-4 2015-09-24 CRAN (R 3.3.0)
scales 0.4.0 2016-02-26 CRAN (R 3.3.0)
SparseM 1.7 2015-08-15 CRAN (R 3.3.0)
stringi 1.1.1 2016-05-27 CRAN (R 3.3.0)
stringr 1.0.0 2015-04-30 CRAN (R 3.3.0)
survival * 2.39-5 2016-06-26 CRAN (R 3.3.0)
survminer * 0.2.2 2016-07-28 CRAN (R 3.3.1)
TH.data 1.0-7 2016-01-28 CRAN (R 3.3.0)
tibble 1.1 2016-07-04 CRAN (R 3.3.0)
tidyr 0.5.1 2016-06-14 CRAN (R 3.3.0)
withr 1.0.2 2016-06-20 CRAN (R 3.3.0)
zoo 1.7-13 2016-05-03 CRAN (R 3.3.0)
write to
Maintainer: Arthur Allignol and Aurelien Latouche
Contact: arthur.allignol at uni-ulm.de
to put survminer
here https://cran.r-project.org/web/views/Survival.html
In a ggsurvplot the legends are very close together. There is almost no spacing between them. Is it possible to increase this spacing?
I tried to insert legend.key.height
in the ggtheme ggtheme = theme_light(legend.key.height=0.2)
and this error comes up
Error in theme_light(legend.key.height = 0.2) :
unused argument (legend.key.height = 0.2)
Is there a right way of increasing this space in a ggsurvplot?
Thanks
Nikolaj
@kassambara Have you considered adding an issue template?
https://github.com/RTCGA/RTCGA/blob/master/ISSUE_TEMPLATE.md
https://github.com/blog/2111-issue-and-pull-request-templates
The survival analysis is still a dynamic area of research which in many cases require complex pre-analysis of assumptions. One assumption of the most popular survival analysis model, the cox proportional hazards model, states that the continuous variable need to be in a linear correlation with the observed times of events. This is know as looking for the functional form of continuous variable in cox model.
This assumption can be checked visually, and if this is not stated then the below graphs might propose what should be the transformation of continuous variable in the model
library(archivist)
aread('MarcinKosinski/Museum/0c289d101131d74ae31429c') -> exampleSurvData
library(survival)
plot(exampleSurvData$size,
resid(coxph(Surv(rectime,censrec)~1, data = exampleSurvData)))
lines(lowess(exampleSurvData$size,
resid(coxph(Surv(rectime,censrec)~1, data = exampleSurvData)),
iter = 0,
f = 0.6))
One might plot the martingale residuals of the null model vs continuous explanatory variables to see that the logarithm
could be applied to this explanatory variable to provide a more linear
form:
plot(log(exampleSurvData$size),
resid(coxph(Surv(rectime,censrec)~1, data = exampleSurvData)))
lines(lowess(log(exampleSurvData$size),
resid(coxph(Surv(rectime,censrec)~1, data = exampleSurvData)),
iter = 0,
f = 0.6))
In my opinion this is a crucial tool in cox model but the proposed plot is ugly and not publication-ready
. I think that recreating such plot in a ggplot is easy to obtain
library(ggplot2)
exampleSurvDataMunged <- data.frame(log_size = log(exampleSurvData$size),
martingale_resid = resid(coxph(Surv(rectime,censrec)~1, data = exampleSurvData)),
log_size_lowess = lowess(log(exampleSurvData$size),
resid(coxph(Surv(rectime,censrec)~1, data = exampleSurvData)),
iter = 0,
f = 0.6)$x,
martingale_resid_lowess = lowess(log(exampleSurvData$size),
resid(coxph(Surv(rectime,censrec)~1, data = exampleSurvData)),
iter = 0,
f = 0.6)$y)
library(ggthemes)
ggplot(exampleSurvDataMunged,
aes(x = log_size,
y = martingale_resid),
col = log_size > martingale_resid) +
geom_point(alpha = 0.5) +
geom_line(aes(log_size_lowess, martingale_resid_lowess)) +
theme_igray(base_family = "mono", base_size = 14)
And the whole analysis became more professional and elegant.
What would you think about adding such functionality to the survminer
package as en extra function ggcoxfunctionalplot
(long name, but couldn't come with better one) ?
The current implementation of survminer
allows to add pvalue of regular log-rank test for statistically significant differences in k-m estimates of survival curves. I am wondering if it is possible to provide a functionality of adding a p-value of the log-rank test for trend instead of regular log-rank on a user demand? Very famous package survMisc
had such possibility [http://stats.stackexchange.com/a/157917/49793] but was removed from CRAN suddenly (probably the reason was new ggplot 2.0.0 version).
Haye you considered merging regular legend with the y.axis.text
element on risk.table
plot?
The the function call could like this:
ggsurvplot(fit, pval = TRUE, conf.int = TRUE, risk.table.ticks.col = TRUE,
risk.table = TRUE, legend = "none" )
And the legend would appear vertically instead of y.axis.text
element on risk.table
plot OR the y.axis.text
element could be coloured to the corresponding strata values?
There are more possibilities than log-rank test for comparing survival curves. One are more vulnerable for early differences and one are more vulnerable for late differences. There are few popular tests, check this : http://stats.stackexchange.com/a/172976/49793
Do you think this is possible to implement more comparing tests and allow user to specify the p-value of which test he would like to add to the survplot?
Are you planning to publish updated version to CRAN?
So far survminer
provides a great tool to display the p-value of the log-rank test for plotted Kaplan-Meier estimates of the survival curves divided on strata.
In many cases the next step in survival analysis, after plotting the survival curves, is fitting the Cox proportional hazards model. I have seen many research posters where biologists shows plots of survival curves that intersect but the p-value of log-rank test allows for the rejection of the null hypothesis (but of the log-rank TEST!) so researchers proceed with Cox model.
Maybe if survminer would support also Cox proportional hazards assumption test that is based on Schoenfeld Residuals, then one could also be aware of the p-value of the assumption test for Cox model https://stat.ethz.ch/R-manual/R-devel/library/survival/html/cox.zph.html.
If thats suits you then pval
parameter could be changed to pval.logrank
and the new parameter pval.cox.zph
could be added and both p-values could be printed somehow. If that suits you then I could prepare a PR.
I know that in most cases survival curves are plotted separately for each variable and the Schoenfeld test should be done for all variables together but this functionality could be useful if one would fit the cox model with 1 variable.
Prepare ggsurvplot.cox.zph
function (or it's overload for this class of object) that would use grid.arrange
to plot many survival curves for different variables (one above another, with 1 risk table at the bottom) and would add a p-value of each variable of the Schoenfeld test to the correspoding survival plot and would add global p-value of the test to tne bottow of the graph. This functionality could be great for models with 2-10 variables, and the output could fit on 1 A4 page of article.
What do you think about that? Would you like such functionality and maybe a sweet PR about it?
Once I've seen an interesting idea of adding counts of censored observation through time.
@prostkop have prepared such graph on a lecture Technics of Data Visualizations
(held on Warsaw University of Technology) https://github.com/pbiecek/TechnikiWizualizacjiDanych/blob/master/MINI_MIMUW_2014/Miniaturka/Faza%203/Szewczyk_Prostko_Ryciak_Ryciuk/3.png
I think it could be a good additional feedback to survival curves, so that one could realize: how do survival curves look like, what is the number of risk set AND what is the cause that the risk set become smaller: is it caused by events or by censored events ?
So the final ggsurvplot could consist of 3 plots: KM-curves, risk.table + cens density/barplot?
@kassambara Thanks for your great work in creating survminer.
I have one suggestion about xlim parameter.
As I understand more-or-lves when a user specifies xlim
then this is added to plot
and table
parts
resul$plot <- resul$plot + scale_x_continuous()
resul$table <- resul$table + scale_x_continuous()
I assume the only situation in which a user would like to cut axes is when there exists a specific time point after which there are only few patients. Like on the example below
library(RTCGA) # survivalTCGA is github only function
library(RTCGA.clinical)
library(survminer)
library(survival)
survivalTCGA(BRCA.clinical, OV.clinical,
extract.cols = "admin.disease_code") -> BRCAOV.survInfo
fit <- survfit(Surv(times, patient.vital_status)~admin.disease_code,
data = BRCAOV.survInfo)
# Customize the output and then print
#++++++++++++++++++++++++++++++++++++
ggsurvplot(fit, pval = TRUE, conf.int = TRUE,
risk.table = TRUE)
In such situation one might not be interested in time below 2000 days. So He would like to provide a limits for xlim and use xlim
(erroneously) like this
ggsurvplot(fit, pval = TRUE, conf.int = TRUE,
risk.table = TRUE, xlim = c(0,200))
Careful R user might notice the error
Warning messages:
1: Removed 1005 rows containing missing values (geom_path).
2: Removed 710 rows containing missing values (geom_point).
3: Removed 1 rows containing missing values (geom_text).
4: Removed 6 rows containing missing values (geom_text).
and might notice that the graph does not correspond to the previous one.
What have happened is that: first the rows with higer survival times were removed, and then the survival curves where calculated. Which is not the real issue. One would like to still get the smae survival estimates. So I think the coord_cartesian
is the answer for this problem
ggsurvplot(fit, pval = TRUE, conf.int = TRUE,
risk.table = TRUE) -> res
res$plot <- res$plot + coord_cartesian(xlim = c(0,2000))
res$table <- res$table + coord_cartesian(xlim = c(0,2000))
res
Which has the same survival curves as the first graph, but it looks like the risk table is broken.
Could you please be so kind and think about this issue, and change it to coord_cartesian
with proper risk.table as I am unable to fix your code so that risk.table would look elegant after coord_cartesian?
This is the issue I have also when woking with the survMisc
packag which was removed from CRAN suddenly 3 weeks ago.
Hi @MarcinKosinski,
I'm writing series of blog posts on survival analyses using survminer for visualization part. Would you, please, clarify for me the two points below:
In the description section, it's stated that ggcoxfunctional() displays graphs of continuous explanatory variable against martingale residuals of null cox proportional hazards model [coxph(Surv(time, event)~1], for each term.
However, in the R script, each continuous variable is plotted against the martingale residuals of a univariate cox model with the covariate [coxph(Surv(time, event)~explanatory.variable]
Is it OK? or should we change something in the description|R script.?
In all of examples I have seen, for assessing the nonlinearity of a continuous variable, people plot the continuous variable against the martingale residuals of the whole Cox model (Cox model with all covariates). This is not the case for ggcoxfunctional(). To be honest, the reason of this difference is not clear in my mind.
Could you, please clarify this for me?
Thank you in advance,
Best,
/A
How can I save a plot inside a function ?
ggsave does not work.
I had some time to try it out, and it works perfect.
However, I would encourage you to make two other adjustments/possibilities.
You should be able to remove the “+” sign that indicate censored data, both
a. from the end of the curve (in case of no censored data), and
b. from the legends.
You should be able to adjust the number of legends, independent of the number of curves. This means you can have 6 curves (2 groups of 3 replicates (replicates with the same linetype)) and 2 legends that show the 2 groups. If I try this now, I get:
Error in .check_legend_labs(fit, legend.labs) :
The length of legend.labs must should be 6
Cheers
Nikolaj
Have you thought about submitting survminer to the http://www.r-bloggers.com/r-projects-at-google-summer-of-code-2016/ ?
I received the following message by email from a survminer user:
I would like to put into the plot some custom annotations (chi value), but by now i have not sorted out how to put a text in the plot.
May be you have a clue.
KS
Relating to #2 I am trying to post-customize the result theme of the survplot but it looks like colour and fill and pre-determined so post-customization triggers warnings like this
> # prepare survival data
> library(RTCGA.clinical)
Loading required package: RTCGA
Welcome to the RTCGA (version: 1.1.14).
> survivalTCGA(BRCA.clinical, OV.clinical, extract.cols = "admin.disease_code") -> BRCAOV.survInfo
> times = "times"
> status = "patient.vital_status"
> explanatory.names = "admin.disease_code"
> x = BRCAOV.survInfo
>
> # fit survival estimates
> library(survival)
> formu <- eval(as.formula(paste0("survival::Surv(", times, ",", status, ") ~ ",
+ paste0(explanatory.names, collapse = " + "))))
> fit <- do.call(survival::survfit, list(formula = formu, data = x))
> library(survminer)
Loading required package: ggplot2
> # create survival plot
> ggsurvplot(fit,
+ risk.table = TRUE,
+ risk.table.y.text.col = TRUE,
+ legend = "none",
+ conf.int = TRUE,
+ pval = TRUE) -> survplot
> # customize theme
> library(ggthemes)
> survplot$table <- survplot$table + scale_fill_pander() + scale_colour_pander()
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
> survplot$plot <- survplot$plot + scale_fill_pander() + scale_colour_pander()
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
I know that this warning messages are not serious but I would like to know how to omit those warnings in case someone not skilled might think it's a serious problem. Do you know whether I can specify parameters of ggsurvplot so that I would not have such warnings? Or do I can somehow specify those scale
functions in the theme
argument of ggsurvplot
?
Thanks in advance.
I have seen that you are using risky parameter eval
with default environment = parent.frame()
https://github.com/kassambara/survminer/blob/master/R/ggsurvplot.R#L470
I am developing an [RTCGA](https://github/RTCGA/RTCGA)
package for simple access to TCGA data with as simple plot functions as possible, since the target group are mainly biologists. I have appreacieated survminer
as a alternative for survMisc
and I am really glad, that my suggestions help upgrading survminer
which result in better functionalities in RTCGA
package.
I have wrote a wprapper for ggsurvplot
in kmTCGA
function :
https://github.com/RTCGA/RTCGA/blob/master/R/kmTCGA.R#L53-L87 where I prepare survfit
from names of parameters. This is comfortable for biologist because they don't need to bother about learning formula
R specifications.
I have occured such an error with this function which brakes when I pass pval = TRUE
# install_github('RTCGA/RTCGA')
library(RTCGA)
## Extracting Survival Data
library(RTCGA.clinical)
survivalTCGA(BRCA.clinical, OV.clinical, extract.cols = "admin.disease_code") -> BRCAOV.survInfo
# first munge data, then extract survival info
library(dplyr)
BRCA.clinical %>%
filter(patient.drugs.drug.therapy_types.therapy_type %in%
c("chemotherapy", "hormone therapy")) %>%
rename(therapy = patient.drugs.drug.therapy_types.therapy_type) %>%
survivalTCGA(extract.cols = c("therapy")) -> BRCA.survInfo.chemo
# first extract survival info, then munge data
survivalTCGA(BRCA.clinical,
extract.cols = c("patient.drugs.drug.therapy_types.therapy_type")) %>%
filter(patient.drugs.drug.therapy_types.therapy_type %in%
c("chemotherapy", "hormone therapy")) %>%
rename(therapy = patient.drugs.drug.therapy_types.therapy_type) -> BRCA.survInfo.chemo
## Kaplan-Meier Survival Curves
kmTCGA(BRCAOV.survInfo, explanatory.names = "admin.disease_code", pval = TRUE)
Hide Traceback
Rerun with Debug
Error in eval(expr, envir, enclos) : object 'formu' not found
6 eval(expr, envir, enclos)
5 eval(fit$call$formula)
4 survival::survdiff(eval(fit$call$formula), data = eval(fit$call$data)) at ggsurvplot.R#470
3 .get_pvalue(fit) at ggsurvplot.R#346
2 ggsurvplot(fit, risk.table = risk.table, conf.int = conf.int,
pval = pval, main = main, ...) at kmTCGA.R#73
1 kmTCGA(BRCAOV.survInfo, explanatory.names = "admin.disease_code",
pval = TRUE)
So I understand from that error is:
kmTCGA passes fit in character mode to ggsurvplot, which uses .get_pvalue
that eval
the formula call in the environment of .get_pvalue
where the variable times
passed to kmTCGA
is not seen, since eval
uses default environment parent.frame()
.
I have no proposition for workaround for this. Do you know any function as match_all_parent_frames_levels
? or get_anywhere
/ getAnywhere()
? If you have any suggestion you could fix survminer
or provide a PR for RTCGA
. I would really appreciate that.
I think from this team work both packages may benefit.
Hi again,
sorry for bringing up all these issues here, but since ggplot was updated, my code is pretty much messed up and it is really hard to fix it.
Before, the proportion of my plot to risk table was pretty nice. You could clearly see if curves cross or not.
Using the same code now, I get approximately this:
I have to hand in a report very soon and I plottet my curves with the pre-updated version, but I made some mistakes (which I can't fix now after the update....).
I'd appreciate some suggestions to fix this :)
Thanks
Feli
Hi @MarcinKosinski ,
As you know, In the field of cancer genomics, biologists are sometimes interested to know whether the expression profile of their favorite gene, say FGFR3, is associated with patients' prognostic. To answer to this question, one can use cox univariate analysis. They want also sometimes to split patients in FGFR3high and FGFR3low. One can arbitrary split patients into 2-3-4 groups using quartiles (q1, q2, q3).
An interesting alternative is provided by maxstat(maximally selected rank statistics) which has several advantages. First, there is no need to transform the time-dependent end point. Second, the test calculates an exact cut-off point, which can be estimated using several methods and approximations, and the discrimination power is also evaluated and estimated with a P value (type I error) 1.
See some examples in this pdf (maxstat is used): http://genomicscape.com/temp/survival_TIE3ByWMo9_plot.pdf
What do you think about adding elegant maxtat visualization support in survminer?
(I have R base scripts for that)
The philosophy of the function would be as follow:
############
# Function computing maximally selected rank test for a list of variables (genes)
#############
# data: data frame containing survival info and gene expression data
# event,time: column names containing event and time data
# variables: characther vector containing gene names: c("FGFR3", "DEPDC1", "IGF1R")
# p: pvalue threshold. only gene with pvalue <= 0.05 will be kept in the final output
# p.adjust: if TRUE, pvalues will be adjusted for multiple testing correction using Benjamini-Hochberg method
xxx_maxstat <- function(data, event, time, variables, p = 0.05,
p.adjust = TRUE, adjust.method = "BH")
{
- Compute max stat for each gene and estimate the optimal cut-point
- Dichotomize each gene based on its optimal cutpoint
- return a mxst object data frame containing gene names, optimal cutpoint and corresponding dichotomized value
}
# S3 method
ggsurvplot.mxst <- function(mxt){
- Visualize mxstat objects
- generate a pdf if multiple genes
}
Articles using maxstat:
Could you be so kind and create e-mail notification for this repository?
Settings -> Webhooks & services -> Add Service -> Email -> and paste0 mine gmail address?
I strongly advice you to add your e-mail address also and create a filter for GitHub notifications on your e-mail-box.
Hi
I installed the latest version from github, but I still have the black dots in the risk table.
Also, if I use this code now:
ggsurvplot(KMfit, pval=TRUE, risk.table=TRUE,risk.table.height = 0.4, table.col = "strata", font.main = c(16, "plain", "black"), font.x = c(12, "plain", "black"), font.y = c(12, "plain", "black"), font.legend = c(12,"plain","black"),main="Sex specific survival",legend="top",legend.title="Sex",legend.labs=c("Women","Men"));
Why is there no x- and y-lab anymore (as a line), but only this "-" ? And how can I change that (without having lines within the plot)?
Cheers,
Feli
Each of the ggsurvplot
objects should have a p-value printed when ggsurvplot()
is applied over a list of formulas or a list of survfit
objects.
Where f
is a list of formulas and dat
is my data, the following works and correctly prints the p-value.
ggsurvplot(survfit(f[[1]], dat), pval = TRUE)
The following piece of code doesn't work, however, when I want to do apply over all elements in f
:
lapply(f, function(x) ggsurvplot(survfit(x, dat), pval = TRUE))
# Error in survival::survdiff(eval(fit$call$formula), data = eval(fit$call$data)) :
# The 'formula' argument is not a formula
When i try to apply over a list of survfit
objects, say in s
, then I get this:
s <- lapply(f, function(x) survfit(x, dat))
lapply(s, function(x) ggsurvplot(x, pval = TRUE))
# Error in survival::survdiff(eval(fit$call$formula), data = eval(fit$call$data)) :
# The 'formula' argument is not a formula
library(survminer)
library(survival)
f1 <- Surv(futime, fustat) ~ resid.ds
f2 <- Surv(futime, fustat) ~ age
f <- list(f1, f2)
s <- lapply(f, function(x) survfit(x, ovarian))
lapply(s, function(x) ggsurvplot(x, pval = TRUE))
# Error in survival::survdiff(eval(fit$call$formula), data = eval(fit$call$data)) :
# The 'formula' argument is not a formula
session_info()
# please paste here the result of
devtools::session_info()
Session info -----------------------------------------------------------------------------------------------------------------------------------------------
setting value
version R version 3.3.1 (2016-06-21)
system x86_64, darwin13.4.0
ui RStudio (0.99.902)
language (EN)
collate en_CA.UTF-8
tz America/Vancouver
date 2016-07-28
Packages ---------------------------------------------------------------------------------------------------------------------------------------------------
package * version date source
assertthat 0.1 2013-12-06 CRAN (R 3.3.0)
biostatUtil * 0.1.0.9050 2016-07-27 local
broom 0.4.1 2016-06-24 CRAN (R 3.3.0)
car 2.1-2 2016-03-25 CRAN (R 3.3.0)
class 7.3-14 2015-08-30 CRAN (R 3.3.1)
codetools 0.2-14 2015-07-15 CRAN (R 3.3.1)
coin 1.1-2 2015-11-16 CRAN (R 3.3.0)
colorspace 1.2-6 2015-03-11 CRAN (R 3.3.0)
DBI 0.4-1 2016-05-08 CRAN (R 3.3.0)
Deducer 0.7-9 2015-12-29 CRAN (R 3.3.0)
devtools 1.12.0 2016-06-24 CRAN (R 3.3.0)
digest 0.6.9 2016-01-08 CRAN (R 3.3.0)
doBy 4.5-15 2016-03-31 CRAN (R 3.3.0)
dplyr * 0.5.0 2016-06-24 CRAN (R 3.3.0)
e1071 1.6-7 2015-08-05 CRAN (R 3.3.0)
effects 3.1-1 2016-03-29 CRAN (R 3.3.0)
foreign 0.8-66 2015-08-19 CRAN (R 3.3.1)
GGally * 1.2.0 2016-07-01 CRAN (R 3.3.0)
ggplot2 * 2.1.0 2016-03-01 CRAN (R 3.3.0)
gridExtra * 2.2.1 2016-02-29 CRAN (R 3.3.0)
gtable 0.2.0 2016-02-26 CRAN (R 3.3.0)
iplots 1.1-7 2013-12-03 CRAN (R 3.3.0)
JavaGD 0.6-1 2012-09-13 CRAN (R 3.3.0)
JGR 1.7-16 2013-12-21 CRAN (R 3.3.0)
KMsurv 0.1-5 2012-12-03 CRAN (R 3.3.0)
labeling 0.3 2014-08-23 CRAN (R 3.3.0)
lattice 0.20-33 2015-07-14 CRAN (R 3.3.1)
lme4 1.1-12 2016-04-16 CRAN (R 3.3.0)
magrittr * 1.5 2014-11-22 CRAN (R 3.3.0)
MASS 7.3-45 2016-04-21 CRAN (R 3.3.1)
Matrix 1.2-6 2016-05-02 CRAN (R 3.3.1)
MatrixModels 0.4-1 2015-08-22 CRAN (R 3.3.0)
memoise 1.0.0 2016-01-29 CRAN (R 3.3.0)
mgcv 1.8-12 2016-03-03 CRAN (R 3.3.1)
minqa 1.2.4 2014-10-09 CRAN (R 3.3.0)
mnormt 1.5-4 2016-03-09 CRAN (R 3.3.0)
modeltools 0.2-21 2013-09-02 CRAN (R 3.3.0)
multcomp 1.4-6 2016-07-14 CRAN (R 3.3.1)
munsell 0.4.3 2016-02-13 CRAN (R 3.3.0)
mvtnorm 1.0-5 2016-02-02 CRAN (R 3.3.0)
nlme 3.1-128 2016-05-10 CRAN (R 3.3.0)
nloptr 1.0.4 2014-08-04 CRAN (R 3.3.0)
nnet 7.3-12 2016-02-02 CRAN (R 3.3.1)
pbkrtest 0.4-6 2016-01-27 CRAN (R 3.3.0)
plyr * 1.8.4 2016-06-08 CRAN (R 3.3.0)
png 0.1-7 2013-12-03 CRAN (R 3.3.0)
psych 1.6.6 2016-06-28 CRAN (R 3.3.0)
quantreg 5.26 2016-06-07 CRAN (R 3.3.0)
R6 2.1.2 2016-01-26 CRAN (R 3.3.0)
Rcpp 0.12.6 2016-07-19 CRAN (R 3.3.1)
reshape 0.8.5 2014-04-23 CRAN (R 3.3.0)
reshape2 1.4.1 2014-12-06 CRAN (R 3.3.0)
rJava 0.9-8 2016-01-07 CRAN (R 3.3.0)
sandwich 2.3-4 2015-09-24 CRAN (R 3.3.0)
scales 0.4.0 2016-02-26 CRAN (R 3.3.0)
SparseM 1.7 2015-08-15 CRAN (R 3.3.0)
stringi 1.1.1 2016-05-27 CRAN (R 3.3.0)
stringr 1.0.0 2015-04-30 CRAN (R 3.3.0)
survival * 2.39-5 2016-06-26 CRAN (R 3.3.0)
survminer * 0.2.2 2016-07-28 CRAN (R 3.3.1)
TH.data 1.0-7 2016-01-28 CRAN (R 3.3.0)
tibble 1.1 2016-07-04 CRAN (R 3.3.0)
tidyr 0.5.1 2016-06-14 CRAN (R 3.3.0)
withr 1.0.2 2016-06-20 CRAN (R 3.3.0)
zoo 1.7-13 2016-05-03 CRAN (R 3.3.0)
One expects that this call will install survminer
with it's vignette
> library(devtools);install_github("kassambara/survminer", build_vignettes = TRUE, force = TRUE)
Downloading GitHub repo kassambara/survminer@master
from URL https://api.github.com/repos/kassambara/survminer/zipball/master
Installing survminer
Skipping 1 unavailable package: RTCGA.clinical
'/usr/lib/R/bin/R' --no-site-file --no-environ --no-save --no-restore --quiet CMD INSTALL \
'/tmp/RtmpR1Lyfb/devtoolse7a3ebc55ce/kassambara-survminer-47cf71a' \
--library='/home/mkosinski/R/x86_64-pc-linux-gnu-library/3.3' --install-tests
* installing *source* package ‘survminer’ ...
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded
* DONE (survminer)
Reloading installed survminer
But when I try to use browseVignettes
I get the following error
> library(survminer)
> browseVignettes('survminer')
No vignettes found by browseVignettes("survminer")
I have had similar problem with RTCGA package and solved it like this
and the only solution I can provide is to add a zzz.R
file with such an entry
https://github.com/RTCGA/RTCGA/blob/master/R/zzz.R#L17-L24
but this move knitr
from Suggests to Imports` (probably) - I'm not sure
session_info()
# please paste here the result of
> session_info()
Session info --------------------------------------------------------------------------------------------
setting value
version R version 3.3.0 (2016-05-03)
system x86_64, linux-gnu
ui RStudio (0.99.879)
language English
collate pl_PL.UTF-8
tz <NA>
date 2016-06-02
Packages ------------------------------------------------------------------------------------------------
package * version date source
colorspace 1.2-6 2015-03-11 CRAN (R 3.3.0)
curl 0.9.7 2016-04-10 CRAN (R 3.3.0)
devtools * 1.11.1 2016-04-21 CRAN (R 3.3.0)
digest 0.6.9 2016-01-08 CRAN (R 3.3.0)
ggplot2 * 2.1.0 2016-03-01 CRAN (R 3.3.0)
git2r 0.15.0 2016-05-11 CRAN (R 3.3.0)
gtable 0.2.0 2016-02-26 CRAN (R 3.3.0)
httr 1.1.0 2016-01-28 CRAN (R 3.3.0)
lattice 0.20-33 2015-07-14 CRAN (R 3.2.1)
magrittr 1.5 2014-11-22 CRAN (R 3.3.0)
Matrix 1.2-6 2016-05-02 CRAN (R 3.3.0)
memoise 1.0.0 2016-01-29 CRAN (R 3.3.0)
munsell 0.4.3 2016-02-13 CRAN (R 3.3.0)
plyr 1.8.3 2015-06-12 CRAN (R 3.3.0)
R6 2.1.2 2016-01-26 CRAN (R 3.3.0)
Rcpp 0.12.5 2016-05-14 CRAN (R 3.3.0)
scales 0.4.0 2016-02-26 CRAN (R 3.3.0)
survival 2.39-4 2016-05-11 CRAN (R 3.3.0)
survminer * 0.2.1.900 2016-06-02 Github (kassambara/survminer@47cf71a)
withr 1.0.1 2016-02-04 CRAN (R 3.3.0)
Hi @MarcinKosinski ,
The function ggcoxdiagnostics() works for type = "martingale" and type = "deviance", but not for type %in% c("score", "schoenfeld", "dfbeta", "dfbetas", "scaledsch", "partial").
Any suggestion?
library(survival)
library(survminer)
res.cox <- coxph(Surv(time, status) ~ age + sex + wt.loss, data = lung)
ggcoxdiagnostics(res.cox, type = "martingale")
ggcoxdiagnostics(res.cox, type = "dfbeta")
Error: Erreur : Aesthetics must be either length 1 or the same as the data (214): x, y
ggcoxdiagnostics(res.cox, type = "schoenfeld")
Error in data.frame(lp = predict(model, type = "lp"), res = residuals(model, :
arguments imply differing number of rows: 214, 152
De plus : Warning message:
In data.row.names(row.names, rowsi, i) :
some row.names duplicated: 3,6,12,16,27,29,34,42,44,45,47,53,56,64,77,87,96,105,108,111,129 --> row.names NOT used
Best,
/A
Question (by e-mail) from a survminer user
Hi
When I make a plot with ggsurvplot and use a ggtheme with grid lines, the vertical grid lines stops at the x axis where the data stops, and are not displayed to the end of the x axis. The vertical grid lines thereby only cover half of the plotting area. Any suggestions to make them cover the whole graph?
There is no problem if I dont specify the xlim parameter, only if I extent the x-axis beyond the limit for the data.
ggsurvplot (my_surv_kmest, size=0.3, main = NULL, conf.int = TRUE, legend.title = "Text", censor= FALSE, surv.scale = "percent", break.time.by = 60, legend.labs = c("Text", "Text2"), linetype = c(1,2), legend = c(0.9,0.9), palette = c(1,1), ggtheme = theme_light(), ylab = "Survival", xlab = "Time (minutes)", xlim = c(0,720), font.x = 9, font.y = 9, font.legend = 6, font.tickslab = 8)
Thanks
Nikolaj
I am testing your package, since survMisc
with great survMisc:::autoplot.survfit
has been removed from CRAN and I occure a funny bug that ggtheme
parameter does not affect risk.table
and the outputed plot looks ridiculous
library(survminer)
library(ggthemes)
ggsurvplot(survfit(Surv(times, patient.vital_status)~dataset,
data = BRCAOV.survInfo),
#pval = TRUE, conf.int = TRUE,
risk.table = TRUE,
ggtheme = theme_bw(base_size = 24, base_family = "serif") ,
break.time.by = 800,
palette = c("#FF9E29", "#86AA00"))
I think changes should be done in those lines of ggsurvplot
https://github.com/kassambara/survminer/blob/master/R/ggsurvplot.R#L338-L343
Hi! First, congrats for the amazing package! I have found a small error in the documentation:
ggsurvplot(fit,
pval = TRUE, conf.int = TRUE,
risk.table = TRUE, # Add risk table
risk.table.col = "strata", # Change risk table color by groups
lienetype = "strata", # Change line type by groups (should be linetype, I think)
ggtheme = theme_bw(), # Change ggplot2 theme
palette = c("#E7B800", "#2E9FDF"))
Have you noticed the awkward behavior of legend = 'left'
?
# install_github('RTCGA/RTCGA')
# install_github('RTCGA/RTCGA.clinical')
library(RTCGA) # survivalTCGA is github only function
library(RTCGA.clinical)
library(survminer)
library(survival)
survivalTCGA(BRCA.clinical, OV.clinical,
extract.cols = "admin.disease_code") -> BRCAOV.survInfo
fit <- survfit(Surv(times, patient.vital_status)~admin.disease_code,
data = BRCAOV.survInfo)
# Customize the output and then print
#++++++++++++++++++++++++++++++++++++
ggsurvplot(fit, pval = TRUE, conf.int = TRUE, main = 'left',
risk.table = TRUE, legend = "left" )
https://www.r-bloggers.com/a-gallery-of-ggplot2-extensions/
Fork the gallery repository on Github.
Create a png thumbnail of an interesting plot from your extension that will look good on a retina screen at 350×300 pixels and put this file in the images directory of the gallery repository.
Add an entry for your extension in the _config.yml file of the repository with the meta data for your extension.
Push your changes and create a pull request.
Dear all,
I`m currently analysing a larger cohort with long follow-up.
As you see in the plot all three groups seem to have the same number of subject (203) which is not true. The survfit identifies 203, 308 and 89 subjects.
Also the number of subjects at risk in the second group increases at week 126 again. This may be due to the fact that no data for the second group is available for this time point.
Did anymore else encounter similar problems?
I'm currently using the latest development version of survminer and R version 3.2.4 Revised (2016-03-16 r70336)
Best wishes
Have you considered attending #eRum2016 with the presentation or the poster about survminer
?
http://www.r-bloggers.com/european-r-users-meeting-meeting-of-r-heroes-poznan-12-14-10-2016/
Dear Marcin
I have a question about the survminer package. I am new to R, and not sure where to ask questions, I hope you can help or redirect me.
I have a survival object based on 6 groups. The following code creates 6 survival curves with ggsurvplot.
ggsurvplot (my_surv_groups, palette = c(1,1,2,1,2,2), linetype = 1)
I can change the color of each line individual – but not the linetype? I thought I could write:
ggsurvplot (my_surv_groups, palette = c(1,1,2,1,2,2),linetype = c(1,1,2,1,2,2))
However, this creates an error:
Error: Aesthetics must be either length 1 or the same as the data (53): size, linetype
In addition: Warning message:
In if (value %in% columns) { :
the condition has length > 1 and only the first element will be used
Can you explain me why “linetype” do not work in the same way as “palette”
library(survminer)
library(survival)
lung$fake_groups <- sample(1:6, size = nrow(lung), replace = TRUE)
fit<- survfit(Surv(time, status) ~ fake_groups, data = lung)
ggsurvplot(fit, palette = c(1,1,2,1,2,2),linetype = c(1,1,2,1,2,2))
session_info()
# please paste here the result of
devtools::session_info()
> devtools::session_info()
Session info -------------------------------------------------------
setting value
version R version 3.3.0 (2016-05-03)
system x86_64, linux-gnu
ui RStudio (0.99.879)
language English
collate pl_PL.UTF-8
tz <NA>
date 2016-05-30
Packages -----------------------------------------------------------
package * version date source
colorspace 1.2-6 2015-03-11 CRAN (R 3.3.0)
devtools 1.11.1 2016-04-21 CRAN (R 3.3.0)
digest 0.6.9 2016-01-08 CRAN (R 3.3.0)
ggplot2 * 2.1.0 2016-03-01 CRAN (R 3.3.0)
gtable 0.2.0 2016-02-26 CRAN (R 3.3.0)
labeling 0.3 2014-08-23 CRAN (R 3.3.0)
lattice 0.20-33 2015-07-14 CRAN (R 3.2.1)
magrittr 1.5 2014-11-22 CRAN (R 3.3.0)
Matrix 1.2-6 2016-05-02 CRAN (R 3.3.0)
memoise 1.0.0 2016-01-29 CRAN (R 3.3.0)
munsell 0.4.3 2016-02-13 CRAN (R 3.3.0)
plyr 1.8.3 2015-06-12 CRAN (R 3.3.0)
Rcpp 0.12.5 2016-05-14 CRAN (R 3.3.0)
scales 0.4.0 2016-02-26 CRAN (R 3.3.0)
survival * 2.39-4 2016-05-11 CRAN (R 3.3.0)
survminer * 0.2.1.900 2016-05-29 local
withr 1.0.1 2016-02-04 CRAN (R 3.3.0)
Cheers
Nikolaj
Hi there,
as I switched to a new laptop, I am now working with the updated version of survminer. I have two problems with the new version:
1.) I have black dots in my risk table (in the line of M1a and M1c). I am simply using the same code as with the last version, but they always show up if I add the risk table. It would be great to know how I can fix this!
This is my command from before:
ggsurvplot(KMfit,pval=TRUE, risk.table=TRUE,risk.table.col = "strata", font.main = c(16, "plain", "black"), font.x = c(16, "plain", "black"), font.y = c(16, "plain", "black"), font.legend = c(14,"plain","black"),main="IVM Stage specific survival",legend="top", legend.title="IVM status",legend.labs=c("M1a", "M1b", "M1c"))
2.) I have to define the risk.table.height each time now when I use the ggsurvplot command. Before, I could simply run it for 2-3 groups and the default size was fine. Now I get something like in the picture below.
Why is this not working anymore?
If one considers this graph
library(RTCGA.mutations)
library(dplyr)
library(survminer)
mutationsTCGA(BRCA.mutations, OV.mutations) %>%
filter(Hugo_Symbol == 'TP53') %>%
filter(substr(bcr_patient_barcode, 14, 15) == "01") %>% # cancer tissue
mutate(bcr_patient_barcode = substr(bcr_patient_barcode, 1, 12)) ->
BRCA_OV.mutations
library(RTCGA.clinical)
survivalTCGA(
BRCA.clinical,
OV.clinical,
extract.cols = "admin.disease_code"
) %>%
dplyr::rename(disease = admin.disease_code) -> BRCA_OV.clinical
BRCA_OV.clinical %>%
left_join(
BRCA_OV.mutations,
by = "bcr_patient_barcode"
) %>%
mutate(TP53 = ifelse(!is.na(Variant_Classification), "Mut","WILDorNOINFO")) ->
BRCA_OV.clinical_mutations
BRCA_OV.clinical_mutations %>%
select(times, patient.vital_status, disease, TP53) -> BRCA_OV.2plot
kmTCGA(
BRCA_OV.2plot,
explanatory.names = c("TP53", "disease"),
break.time.by = 400,
xlim = c(0,2000)
) -> km_plot
print(km_plot)
produced by ggsurvplot
function, then one can notices that sometimes survival ruves are not very transparent because of the long names of stratas in the legend of risk table.
Do you think it would be possible to have coloured squares instead of names in the labels of risk table? And then the names of stratas could be coloured in regular legend above the survival-plot where there is more place ?
The example solution could look like this (poorly I had only 1 colour :P). This way the more spaced is designed for survival plot
using log directory 'd:/RCompile/CRANguest/R-devel/survminer.Rcheck'
* using R version 3.3.0 beta (2016-04-14 r70486)
* using platform: x86_64-w64-mingw32 (64-bit)
* using session charset: ISO8859-1
* checking for file 'survminer/DESCRIPTION' ... OK
* checking extension type ... Package
* this is package 'survminer' version '0.2.1'
.............
* checking foreign function calls ... OK
* checking R code for possible problems ... NOTE
ggcoxfunctional: no visible global function definition for 'terms'
ggcoxfunctional: no visible global function definition for
'model.matrix'
ggcoxfunctional : <anonymous>: no visible global function definition
for 'as.formula'
ggcoxfunctional : <anonymous>: no visible global function definition
for 'resid'
ggcoxzph: no visible global function definition for 'approx'
Undefined global functions or variables:
approx as.formula model.matrix resid terms
Consider adding
importFrom("stats", "approx", "as.formula", "model.matrix", "resid",
"terms")
to your NAMESPACE file.
* checking Rd files ... OK
* checking Rd metadata ... OK
.......
I've seen in your code that if your specify risk.table = TRUE
then the gridExtra::grid.arrange
function is used and one does not get a ggplot
object as a result and customization is hard.
Is customization only possible through ggtheme
argument? Where one has to write his own function? It also looks funny, as the output plot can not be changed, which it is contrary with ggplot customization paradigm.
That's very odd way of creating ggplot
ggsurvplot(survfit(Surv(times, patient.vital_status)~dataset,
data = BRCAOV.survInfo),
#pval = TRUE, conf.int = TRUE,
risk.table = TRUE,
ggtheme = theme_RTCGA(base_size = 24, base_family = "serif") ,
break.time.by = 800,
palette = c("#FF9E29", "#86AA00"))
theme_RTCGA <- function(base_size, base_family){
theme_grey(base_size = base_size, base_family = base_family) %+replace%
theme(axis.text = element_text(size = rel(0.8)),
axis.ticks = element_line(colour = "black"),
legend.key = element_blank(),
panel.background = element_blank(),
legend.background = element_blank(),
panel.border = element_blank(),
panel.grid.major = element_line(colour = "grey90", size = 0.2),
panel.grid.minor = element_line(colour = "grey98", size = 0.5),
strip.background = element_rect(fill = "grey80", colour = "grey50", size = 0.2))
}
There was one great functionality of dx
function http://www.inside-r.org/packages/cran/survMisc/docs/dxPlot that produced diagnostic plots for cox models. Do you think it would be valuable to add such functionality to survminer?
library(survMisc) # can be downloaded from CRAN from it's archives
data(bmt, package="KMsurv")
bmt <- within(bmt, {
z1 <- z1 -28
z2 <- z2- 28
z3 <- z1*z2
z4 <- as.double( group== 2 )
z5 <- as.double( group== 3 )
z6 <- z8
z7 <- (z7 / 30) - 9
z8 <- z10
})
c1 <- coxph(Surv(t2,d3) ~ z1+z2+z3+z4+z5+z6+z7+z8,
method="breslow",
data=bmt)
dx(c1, what="ph", file="vetDx.pdf")
One could add an example on how the xlim
is working now, and add proper plots (last 3) with the new p-value form.
What would you say if we create a vignette from this blog post :)? We could add this to package, and then it will appear on CRAN and on staticdocs if you rebuild them :)
#34
http://www.r-bloggers.com/survival-plots-have-never-been-so-informative/
What do you think of adding a new section like Blog history
to README.md where we could list all blog posts about survminer. I remeber you must have wrote earlier about survminer so that I have discovered survminer (probably you spread the word on Users of R package
or something like that on Facebook group, where I am banned now :P dunno why).
This better should be a Milestone instead of an Issue but I have no collaborator rights at this repository.
Are we planning to submit survminer ver 0.2.2 before useR2016? Should we also update staticdocs? http://www.sthda.com/english/rpkgs/survminer/
Check this plot in which survival curves and confidence intervals are customized but one can't change the color of risk.table.y.text.col
[https://github.com//issues/8]
# prepare survival data
library(RTCGA.clinical)
survivalTCGA(BRCA.clinical, OV.clinical, extract.cols = "admin.disease_code") -> BRCAOV.survInfo
times = "times"
status = "patient.vital_status"
explanatory.names = "admin.disease_code"
x = BRCAOV.survInfo
# fit survival estimates
library(survival)
formu <- eval(as.formula(paste0("survival::Surv(", times, ",", status, ") ~ ",
paste0(explanatory.names, collapse = " + "))))
fit <- do.call(survival::survfit, list(formula = formu, data = x))
library(survminer)
# create survival plot
ggsurvplot(fit,
risk.table = TRUE,
risk.table.y.text.col = TRUE,
legend = "none",
conf.int = TRUE,
pval = TRUE) -> survplot
# customize theme
library(ggthemes)
survplot$table <- survplot$table + scale_fill_pander() + scale_colour_pander()
survplot$plot <- survplot$plot + scale_fill_pander() + scale_colour_pander()
https://github.com/kassambara/survminer/blob/master/R/ggsurvplot.R#L338-L343 I know that the issues is somewhere over here but I am not so familiar with your package (YET!) to provide a useful pull request.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.