之前师兄把数据整理和画图的代码给了我,由此开始了漫长的挣扎之路...
一开始,他说用source
来直接source整段代码进server.R中,但是我到现在都还没有搞懂怎么source
既然不会就只能用笨方法了,直接复制粘贴到server里面吧!要把直接在Rstudio中跑的代码变成app中里面的一个功能,首先要做的就是把固定的文件替换成用户上传的文件,试验中就是input$file1
啦。所以,首先先把数据整理的一段代码复制到server里面:
library("readr")
library(Biobase)
source("D:/Hard work/R_function.R")
options(stringsAsFactors=F)
########cut off init
p_value <- 0.05 # p value of FDR
lfc <- 0.58 #logFC
args <-commandArgs(T)
args[1] <- input$file1
########load data
countData1 <- as.data.frame(read_delim(args[1],delim = "\t"))
dim(countData1)
rownames(countData1) <- countData1$id
countData=countData1[,-1]
###########pheno data loading
colData <- get_pheno(x = colnames(countData),label1 = "T",label2 = "N",group1 = "Tumor",group2 = "Normal")
countData <- countData[,as.character(rownames(colData))]
colData$Type <- as.factor(colData$Type)
type_level <- levels(as.factor(colData$Type))
comb <- combn(type_level,2)
#########filter low-abandance circRNA ; the step has been done in node1:filter_circ
# countData <- countData[which(rowSums(countData > 0) >= 2),] #a Count>0 in at least 2 samples
# dim(countData)
# ###############type specific
##############edgeR
#source("./R_function.R")
#sharedCirc_edgeR_tmp <- edgeR_test(expre_mat = shared_circ,group_mat = colData,test_method = "LRT" )
sharedCirc_edgeR <-edgeR_test(expre_mat = countData,group_mat = colData)
DE_sharedCirc_res = subset(sharedCirc_edgeR,FDR <= p_value & abs(logFC) >= lfc)
select <- DE_sharedCirc_res[order(DE_sharedCirc_res$logFC, decreasing = TRUE),]
Circ_norm_edgeR=cpm(countData) ###norm expres_mat
rownames(Circ_norm_edgeR)=countData1$id
sharedCirc_DE_edgeR=Circ_norm_edgeR[rownames(select),]
#all DE
DE_list <- c(rownames(DE_sharedCirc_res))
然而发现自己太年轻,系统直接报错,找不到“input”,想了一下这不是废话吗,刚打开怎么会有input,然后要别人怎么整理数据嘛
所以我就想着弄一个条件语句,把数据整理打包成一个功能,且在有input的时候才会动,至于有没有必要打包成一个功能,还要靠后面试验一下。
想来想去觉得一时半会想不出来,所以先试一下最笨的方法:在每个tab的output代码里都加进这一段,只不过是最后图不一样而已
所以拿火山图试了一下,代码是
output$dmplot <- renderPlot{
if(is.null(input$file2)){return()}
...
args[1] <- input$file2$datapath
...
volcanoplot()
}
实际上,最重要的是中间args[1]
那一句,通过这个方法, 结果是可行的,只不过终于明白了当初加进度条的目的,实在是太慢了。而且如果每个模块的每个tab里面都塞这么一段代码的话,整个应用的速度会不会被严重拖慢,这都是要考虑的问题。现在再尝试一下把它弄整洁一点。
可能可以在每一个模块前面加一个reactive()
解决方案①(只能完成但是不能控制):
output$dmplot <- renderPlot({
if(is.null(input$file2)){return()}
########cut off init
p_value <- 0.05 # p value of FDR
lfc <- 0.58 #logFC
args <-commandArgs(T)
#args[1] <- "matrix/11_7//filter_input_count.mat"
args[1] <- input$file2$datapath
########load data
countData1 <- as.data.frame(read_delim(args[1],delim = "\t"))
dim(countData1)
rownames(countData1) <- countData1$id
countData=countData1[,-1]
###########pheno data loading
colData <- get_pheno(x = colnames(countData),label1 = "T",label2 = "N",group1 = "Tumor",group2 = "Normal")
countData <- countData[,as.character(rownames(colData))]
colData$Type <- as.factor(colData$Type)
type_level <- levels(as.factor(colData$Type))
comb <- combn(type_level,2)
sharedCirc_edgeR <-edgeR_test(expre_mat = countData,group_mat = colData)
DE_sharedCirc_res = subset(sharedCirc_edgeR,FDR <= p_value & abs(logFC) >= lfc)
select <- DE_sharedCirc_res[order(DE_sharedCirc_res$logFC, decreasing = TRUE),]
Circ_norm_edgeR=cpm(countData) ###norm expres_mat
rownames(Circ_norm_edgeR)=countData1$id
sharedCirc_DE_edgeR=Circ_norm_edgeR[rownames(select),]
#all DE
DE_list <- c(rownames(DE_sharedCirc_res))
volcano_plot(sharedCirc_edgeR,c("Normal","Tumor"))
})
当上传了文件,就开始算,但其实这个最后是不可行的,因为:1. 到时可能会上传多个文件;2. 没有控制按钮是不行的,你以为想画图就画?
解决方案②(添加actionButton()
):
然后失败了
解决解决方案②:用eventReactive()
对pl赋值,并用actionButton
进行控制,然后直接在renderPlot()
中写上pl(),就可以生成图表。这样起码可以在每个tab中加上一个开始按钮,然后需要时再计算画图,每个tab之间相互独立,但是这样的坏处是,每作一张图就要重复计算数据,很不必要并且浪费时间。不过怎么说总算有了一种可行的方法。
解决方案③(最完美):
只用reactive()
:先用一个example把需要计算的文件位置占住,使得不会报错,然后再通过conditionalPanel
来实现上传文件的切换,这样就不用考虑先后顺序的问题。上传和计算的部分用reactive分开,最后用list返回多个对象,给下面作图做准备。但是这样做的缺点是一打开那个页面它就会自动运算,比如想直接上传文件计算,还要等example先算一遍。所以有一个更加独立封闭的方法。
用eventReactive()
:上传文件部分不变,计算部分加一个控制的actionButton()
,在按下按钮之后才会开始运算,这样就会提高网站的速度。
例如:
dmdataprocess <- eventReactive(input$dmbutton,{
....
plots <- list(a=sharedCirc_edgeR, b=DE_sharedCirc_res, c=colData, d=Circ_norm_edgeR, e=sharedCirc_DE_edgeR, f=DE_list)
return(plots)
})
接着,在下面画图时,需要用到的参数就可用dmdataprocess()$a
诸如此类的表达来表示,注意,因为dmdataprocess是在eventReactive
表达中,因此结构是和函数一样的,所以用的时候要在后面加一个括号。通过这样处理,运算一次便可以生成三张图。
其实较早之前就能正确运用eventReactive了,但是过了这么久才解决,总结这次经验就是:函数的默认返回值是最后一行,用list()
返回多个对象(所以为什么这么简单的事情困扰了这么久)
用actionButton()
触发画图时,用observeEvent()
配合
observeEvent(input$qcbutton,{
output$qcdistri <- renderPlot({
distribution_plot(m6A_anno = qcdatasetinput())
})
})