km.R 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #' Create a KM plot
  2. #'
  3. #' @param x a data frame that contains followup and censored columns
  4. #' @param var a categorical variable to split the data to sub-curves
  5. #' @param comment An additional piece of text to write in the curve
  6. #'
  7. #' @return p probability that curves split by var differ significantly
  8. #'
  9. #' @export
  10. kaplan.meier<-function(x,var,comment=''){
  11. #x should have followup and censored columns
  12. surv.obj<-survival::Surv(x$followup,x$censored)
  13. m=base::max(x$followup)
  14. f<-stats::as.formula(paste('surv.obj',var,sep='~'))
  15. s1<-survival::survfit(f,data=x)
  16. #str(s1)
  17. tit=base::sprintf('Kaplan-Meier plot by %s',var)
  18. cols=base::c('red','blue')
  19. labels=base::c(base::sprintf('%s=true',var),base::sprintf('%s=false',var))
  20. #plot(s1,mark.time=TRUE,col=c('red','blue'),pch=labels,main=tit)
  21. graphics::plot(s1,mark.time=TRUE,col=c('red','blue'),main=tit)
  22. s=survival::survdiff(f,data=x)
  23. #str(s)
  24. p=stats::pchisq(s$chisq, length(s$n)-1, lower.tail = FALSE)
  25. sv=base::sprintf("p=%.3f",p)
  26. nLab=base::sprintf('N=%d',nrow(x))
  27. graphics::text(x=c(0.9*m,0.3*m,0.9*m),y=c(0.2,0.1,0.3),label=c(sv,comment,nLab),cex=1.2)
  28. lLab <- base::gsub("x=","",base::names(s1$strata)) ## legend labels
  29. graphics::legend("top",legend=lLab,col=cols,lty=c(1,1),horiz=FALSE, bty='n')
  30. p
  31. }
  32. set.from.list<-function(var,default,...){
  33. z<-list(...)
  34. set.from.arg.list(var,default,z)
  35. }
  36. #' Set argument value from list or to default value
  37. #'
  38. #' @param var name of value in list
  39. #' @param default value
  40. #' @param z of values, such as labkey.url.params
  41. #'
  42. #' @return value from list or default if missing
  43. #'
  44. #' @export
  45. set.from.arg.list<-function(var,default,z){
  46. if (var %in% base::names(z)) result<-base::unlist(z[[var]])
  47. else result=default
  48. result
  49. }
  50. #' Evaluate a KM plot
  51. #'
  52. #' @param x a data frame that contains followup and censored columns
  53. #' @param var a categorical variable to split the data to sub-curves
  54. #'
  55. #' @return p probability that curves split by var differ significantly
  56. #'
  57. #' @export
  58. kaplan.meier.stats<-function(x,var){
  59. #x should have followup and censored columns
  60. surv.obj<-survival::Surv(x$followup,x$censored)
  61. m=base::max(x$followup)
  62. f<-stats::as.formula(paste('surv.obj',var,sep='~'))
  63. s1<-survival::survfit(f,data=x)
  64. s=survival::survdiff(f,data=x)
  65. p=stats::pchisq(s$chisq, length(s$n)-1, lower.tail = FALSE)
  66. p
  67. }
  68. #' Plot a Kaplan-Meier curve with ggsurvfit
  69. #'
  70. #'@param x data frame containing followup and censored column
  71. #'@param var name of variable to stratify by
  72. #'@param ... other parameters:
  73. #' * varName name of variable for title (NOT GIVEN)
  74. #' * comment additional text to print on plot (empty string)
  75. #' * reorder whether to change order of categorical variable labels in legend (FALSE)
  76. #' * unit unit for time axis
  77. #' * my.legend.title title to set to legend (varName)
  78. #' * my.title title for the plot (Kaplan-Meier plot by varName)
  79. #' * my.labels labels for cases
  80. #' * draw.axis draw title and axis (FALSE)
  81. #' * my.n number of classes (2)
  82. #' * my.ylab label for y axis (Overall survival probability)
  83. #'@return graphical object
  84. #'
  85. #'@export
  86. kaplan.meier.plot.gg<-function(x,var,...){
  87. if (!requireNamespace('ggsurvfit',quiet=TRUE)){
  88. print('ggsurvfit not available. Use rNIX::kaplan.meier function')
  89. return(NULL)
  90. }
  91. #x should have followup and censored columns
  92. surv.obj<-survival::Surv(x$followup,x$censored)
  93. m=base::max(x$followup)
  94. f<-stats::as.formula(paste('surv.obj',var,sep='~'))
  95. #need survfit2
  96. s1<-ggsurvfit::survfit2(f,data=x)
  97. varName=set.from.list('varName',var,...)
  98. tit=base::sprintf('Kaplan-Meier plot by %s',varName)
  99. ylab='Overall survival probability'
  100. comment=set.from.list('comment','',...)
  101. my.labels=set.from.list('my.labels',c(),...)
  102. reorder=set.from.list('reorder',FALSE,...)
  103. unit=set.from.list('unit','day',...)
  104. my.legend.title=set.from.list('my.legend.title','NONE',...)
  105. draw.axis=set.from.list('draw.axis',FALSE,...)
  106. my.title=set.from.list('my.title',tit,...)
  107. my.n=set.from.list('my.n',2,...)
  108. my.ylab=set.from.list('my.ylab',ylab,...)
  109. base::print(base::sprintf('my.n=%f',my.n))
  110. xlab=base::sprintf('Time (%ss)',unit)
  111. if (my.n==4)
  112. cols=base::c('dodgerblue2', 'orchid2','orange','green')
  113. else
  114. cols=base::c('dodgerblue2', 'orchid2')
  115. nc=base::length(cols)
  116. base::print(base::sprintf('nc=%d',nc))
  117. labs <- base::gsub("^.*=","",base::names(s1$strata)) ## legend labels
  118. if (base::length(my.labels)==0){
  119. my.labels <- labs
  120. }
  121. nl=base::length(labs)
  122. nl1=base::length(my.labels)
  123. base::print(base::sprintf('nl=%d nl1=%d',nl,nl1))
  124. if (my.legend.title=='NONE'){
  125. my.legend.title=varName
  126. }
  127. if (reorder){
  128. perm=base::c(2,1)
  129. cols=cols[base::order(perm)]
  130. labs=labs[base::order(perm)]
  131. my.labels=my.labels[base::order(perm)]
  132. }
  133. q<-ggsurvfit::ggsurvfit(s1,lwd=1.0,censor=TRUE,censor.shape='+',censor.size=10)+
  134. ggplot2::ylim(0,1)+
  135. ggsurvfit::add_legend_title(my.legend.title)+
  136. ggsurvfit::add_pvalue("annotation", size = 5)+
  137. #add_pvalue("caption", size = 5)+
  138. ggsurvfit::add_confidence_interval()+
  139. #add_risktable()+
  140. ggplot2::scale_color_manual(values=cols,breaks = labs,labels=my.labels) +
  141. ggplot2::scale_fill_manual(values=cols, breaks = labs,labels=my.labels) +
  142. ggplot2::labs(x=NULL, y=NULL)
  143. if (draw.axis){
  144. q<-q+ggplot2::ggtitle(my.title)+ggplot2::xlab(xlab)+ggplot2::ylab(my.ylab)
  145. }
  146. q
  147. }