R面向对象
最后发布时间:2023-03-26 20:29:00
浏览量:
S4
.hasSlot(object, name)
setOldClass("data.frame")
https://docs.tibco.com/pub/enterprise-runtime-for-R/6.0.0/doc/html/Language_Reference/methods/slot.html
创建类
setClass("Person",
slots = list(name = "character", age = "numeric"))
alice <- new("Person", name = "Alice", age = 40)
alice@name
案例
## 创建父类
setClass("Shape",
slots=list(name="character",shape="character"))
## 创建子类
setClass("Ellipse",
contains="Shape",
slots=list(radius="numeric"),
prototype=list(radius=c(1,1),shape="Ellipse"))
setClass("Circle",
contains="Ellipse",
slots=list(radius="numeric"),
prototype=list(radius = 1,shape="Circle"))
setClass("Rectangle",
contains="Shape",
slots=list(edges="numeric"),
prototype=list(edges=c(1,1),shape="Rectangle"))
setClass("Square",
contains="Rectangle",
slots=list(edges="numeric"),
prototype=list(edges=1,shape="Square"))
setGeneric("getShape",function(obj,...) {
cat("sss")
standardGeneric("getShape")
})
setMethod("getShape","Shape",function(obj,...){
cat(obj@shape,"\n")
})
setGeneric("area",function(obj,...) standardGeneric("area"))
setMethod("area","Ellipse",function(obj,...){
cat("Ellipse Area :\n")
pi * prod(obj@radius)
})
setMethod("area","Circle",function(obj,...){
cat("Circle Area :\n")
pi*obj@radius^2
})
setMethod("area","Rectangle",function(obj,...){
cat("Rectangle Area :\n")
prod(obj@edges)
})
setMethod("area","Square",function(obj,...){
cat("Square Area :\n")
obj@edges^2
})
setGeneric("circum",function(obj,...) standardGeneric("circum"))
setMethod("circum","Ellipse",function(obj,...){
cat("Ellipse Circum :\n")
2*pi*sqrt((obj@radius[1]^2+obj@radius[2]^2)/2)
})
setMethod("circum","Circle",function(obj,...){
cat("Circle Circum :\n")
2*pi*obj@radius
})
setMethod("circum","Rectangle",function(obj,...){
cat("Rectangle Circum :\n")
2*sum(obj@edges)
})
setMethod("circum","Square",function(obj,...){
cat("Square Circum :\n")
4*obj@edges
})
e1<-new("Ellipse",name="e1",radius=c(2,5))
getShape(e1)
circum(e1)
area(e1)
setValidity("Circle",function(object) {
if (object@radius <= 0) stop("Radius is negative.")
})
c1<-new("Circle",name="c1",radius=2)
getShape(c1)
circum(c1)
area(c1)
r1<-new("Rectangle",name="r1",edges=c(2,5))
getShape(r1)
circum(r1)
area(r1)
s1<-new("Square",name="s1",edges=2)
getShape(s1)
circum(s1)
area(s1)
结果
> e1<-new("Ellipse",name="e1",radius=c(2,5))
> getShape(e1)
sssEllipse
> circum(e1)
Ellipse Circum :
[1] 23.92566
> area(e1)
Ellipse Area :
[1] 31.41593
常用方法
library(pryr)
otype(x)
getMethod("circum", "Ellipse") ## 查看泛型函数circum的Ellipse实现
S3与S4区别
S3对象:是基于泛型函数的面向对象机制.S3对象可看作是一个list并有一个名为class的属性.S3没有正式的类型定义
x <- structure(2, class = "foo")
> x<-1
> attr(x,'class')<-'foo'
> x
[1] 1
attr(,"class")
[1] "foo"
> class(x)
[1] "foo"
# 用pryr包的otype函数,检查x的类型
> otype(x)
[1] "S3"
> y <- structure(2, class = "foo")
> y
[1] 2
attr(,"class")
[1] "foo"
> class(y)
[1] "foo"
> otype(y)
[1] "S3"
S3对象的泛型和多态
# 用UseMethod()定义teacher泛型函数
# 用teacher.xxx的语法格式定义teacher对象的行为
#其中teacher.default是默认行为
library(pryr)
teacher <- function(x, ...) UseMethod("teacher")
ftype(teacher)
otype(teacher)
teacher.lecture <- function(x) print("讲课")
teacher.assignment <- function(x) print("布置作业")
teacher.correcting <- function(x) print("批改作业")
teacher.default<-function(x) print("你不是teacher")
a<-'teacher'
attr(a,'class') <- 'lecture' # 给老师变量设置行为
class(a)
teacher(a)
teacher.lecture(a)
methods(teacher)
getAnywhere(teacher.lecture)
plot.default(c(1,2,3))
suppressPackageStartupMessages(library(tidyverse))
library(pryr)
setClass("Shape",
slots=list(name="character",shape="character"))
# setClass("Rectangle",
# contains="Shape",
# slots=list(edges="numeric"),
# prototype=list(edges=c(1,1),shape="Rectangle"))
setGeneric("getShape",function(obj,arg1,arg2) standardGeneric("getShape"))
setMethod("getShape","Shape",function(obj,arg1,arg2) {
cat(obj@name,arg1,arg2)
})
r1<-new("Shape",name="r1")
getShape(r1,"a","sss")
otype(getShape)
ftype(getShape)
showMethods(getShape)
# 查看泛型函数函数实现
getMethod("getShape","Shape")
# > getMethod("getShape","Shape")
# Method Definition:
# function (obj, arg1, arg2)
# {
# cat(obj@name, arg1, arg2)
# }
# Signatures:
# obj
# target "Shape"
# defined "Shape"
################S3################################
getShape <- function(obj,arg1,arg2) UseMethod(generic="getShape",object=obj)
getShape.Shape <- function(obj,arg1,arg2){
cat(obj,arg1,arg2)
}
obj <- "test"
# getShape(obj) # no applicable method for 'getShape' applied to an object of class "character"
attr(obj,'class') <- 'Shape'
class(obj)
getShape(obj,"222","333")
otype(getShape)
ftype(getShape)
# 查看泛型函数函数实现
getShape.Shape
getAnywhere(getShape.Shape)
setClass("Person",slots=list(name="character",age="numeric"))
setGeneric("work",function(object) standardGeneric("work"))
setMethod("work", signature(object = "Person"), function(object) cat(object@name , "is working") )
ftype(work)
# a<-new("Person",name="Conan",age=16)
# work(a)
# ftype(work)
setClass("Shape",slots=list(name="character",shape="character"))
setGeneric("getShape",function(obj,arg1,arg2) tandardGeneric("getShape"))
setMethod("getShape","Shape",function(obj,arg1,arg2) { cat(obj@name,arg1,arg2)})
ftype(getShape)
使用$访问R S4对象
setClass("Shape",
slots=list(name="character",metadata="data.frame"))
metadata <- colData(vsd)|> as.data.frame()
#sample group sizeFactor
#IPMN-6080042 IPMN-6080042 treatment 1.84431497
#IPMN-6080180 IPMN-6080180 treatment 1.87930966
#IPMN-6100221 IPMN-6100221 treatment 0.89195100
#PDAC-1915728 PDAC-1915728 control 1.80253128
#PDAC-6050001 PDAC-6050001 control 4.35214778
#PDAC-6060065 PDAC-6060065 control 0.04433571
r1<-new("Shape",metadata=metadata)
setMethod("$", "Shape",
function(x, name)
{
cat(name)
x@metadata[[name]]
})
r1$sample
#sample[1] "IPMN-6080042" "IPMN-6080180" "IPMN-6100221" "PDAC-1915728" "PDAC-6050001" "PDAC-6060065"
修改S4对象
setClass("Shape",
slots=list(name="character",shape="character"))
setGeneric("getShape",function(obj,arg1,arg2) standardGeneric("getShape"))
setMethod("getShape","Shape",function(obj,arg1,arg2) {
cat(obj@name,arg1,arg2,"\n")
})
r1<-new("Shape",name="wangyang")
r1@name<- "sss"
getShape(r1,"a","sss")
setGeneric("init<-",function(object,value)standardGeneric("init<-"))
setMethod("init<-","Shape", function(object,value) {
object@name <- value
object
})
init(r1) <- "11111111111"
getShape(r1,"a","sss")
##################R S4 OOP的特征######################
## 泛型函数,多态的使用
## 可以函数重写(子类函数与父类同名函数)
## 没有函数重载
## 可以进行序列化与反序列化
#####################################################
#### 泛型函数
setwd("/home/wangyang/workspace/yqs136")
setClass("Shape",
slots=list(name="character",shape="character"))
setGeneric("getShape",function(obj)standardGeneric("getShape"))
setMethod("getShape","Shape",function(obj){
cat("shape: ",obj@shape," name: ",obj@name,"\n")
})
setClass("Rectangle",
contains="Shape",
slots=list(edges="numeric"),
prototype=list(shape="Rectangle"))
setClass("Circle",
contains="Shape",
slots=list(radius="numeric"),
prototype=list(shape="Circle"))
r1<-new("Rectangle",name="Rectangle001",edges=c(2,5))
c2<-new("Circle",name="Circle002",radius=2)
slot(r1,"name")
r1@name
getShape(r1)
getShape(c2)
#### 多态 注:R可以函数重写,就是子类函数可以覆盖父类的同名函数
setMethod("getShape","Rectangle",function(obj){
cat("Rectangle的getShape函数已经被重写!\n")
})
getShape(r1)
getShape(c2)
setMethod("getShape","Circle",function(obj){
cat("Circle的getShape函数已经被重写!\n")
})
getShape(r1)
getShape(c2)
## 没有函数重载
setGeneric("area",function(obj) standardGeneric("area"))
setMethod("area","Circle",function(obj){
cat("Circle Area :\n")
pi*obj@radius^2
})
setMethod("area","Rectangle",function(obj){
cat("Rectangle Area :\n")
prod(obj@edges)
})
area(r1)
area(c2)
setGeneric("area",function(obj,value) standardGeneric("area"))
setMethod("area","Shape",function(obj,value){
cat(obj@name,value,"\n")
})
area(r1,"aa")
area(r1,"bb")
## 可以进行序列化与反序列化
saveRDS(r1,file="rds/r1.rds")
r1 <- readRDS("rds/r1.rds")
r1@name
##################使用 R S4带来的好处#####################
# 将结果存储在一个对象里
# 快速修改函数的实现
# 函数debug方式1:给参数附上具体的值
# 函数debug方式2:通过Debug的方式进行调试
########################################################
#### 将结果存储在一个对象里
source("/home/wangyang/workspace/yqs136/R/S4/class.R")
miRNA_Obj <- readRDS("/home/wangyang/workspace/yqs136/rds/miRNA_Obj.rds")
piRNA_Obj <- readRDS("/home/wangyang/workspace/yqs136/rds/piRNA_Obj.rds")
miRNA_Obj@DegDFs[["miRNA_4023_vs_2558_RWP1"]]@deg |> write_tsv(file="deg/miRNA_4023_vs_2558_RWP1.tsv")
miRNA_Obj@DegDFs[["miRNA_IPMN_vs_PDAC"]]@deg |> write_tsv(file="deg/miRNA_IPMN_vs_PDAC.tsv")
miRNA_Obj@DegDFs[["miRNA_NORMAL_vs_IPMN"]]@deg |> write_tsv(file="deg/miRNA_NORMAL_vs_IPMN.tsv")
miRNA_Obj@DegDFs[["miRNA_SCRAMBLE_vs_2558_RWP1"]]@deg |> write_tsv(file="deg/miRNA_SCRAMBLE_vs_2558_RWP1.tsv")
piRNA_Obj@DegDFs[["piRNA_4023_vs_2558_RWP1"]]@deg |> write_tsv(file="deg/piRNA_4023_vs_2558_RWP1.tsv")
piRNA_Obj@DegDFs[["piRNA_IPMN_vs_PDAC"]]@deg |> write_tsv(file="deg/piRNA_IPMN_vs_PDACtsv")
piRNA_Obj@DegDFs[["piRNA_NORMAL_vs_IPMN"]]@deg |> write_tsv(file="deg/piRNA_NORMAL_vs_IPMN.tsv")
piRNA_Obj@DegDFs[["piRNA_SCRAMBLE_vs_2558_RWP1"]]@deg |> write_tsv(file="deg/piRNA_SCRAMBLE_vs_2558_RWP1.tsv")
miRNA_Obj <- volcano(miRNA_Obj,name="miRNA_4023_vs_2558_RWP1")
miRNA_Obj <- intersectGene(miRNA_Obj)
# 查看miRNA_4023_vs_2558_RWP1组差异基因个数
miRNA_Obj@DegDFs[["miRNA_4023_vs_2558_RWP1"]]@deg |> dim()
# 查看miRNA_4023_vs_2558_RWP1组数据上调和下调差异基因
table(miRNA_Obj@DegDFs[["miRNA_4023_vs_2558_RWP1"]]@degSig$direction)
# 查看miRNA_4023_vs_2558_RWP1组所有差异的基因
miRNA_Obj@DegDFs[["miRNA_4023_vs_2558_RWP1"]]@degSig$symbol
getwd()
#### 快速修改函数的实现
source("/home/wangyang/workspace/yqs136/R/S4/class.R")
miRNA_Obj <- volcano(miRNA_Obj,name="miRNA_SCRAMBLE_vs_2558_RWP1")
miRNA_Obj@DegDFs[["miRNA_4023_vs_2558_RWP1"]]@expr
setMethod("runDeg","YQS136",function(obj,name,...){
metadata <- getMetadata(obj,...)
expr <- obj@expr[,metadata$sample]
metadata$group <- factor(metadata$group,levels=c("control","treatment"))
metadata$batch <- factor(metadata$batch)
message("expr column and metadata row: ",identical(colnames(expr),metadata$sample))
####################limma的逻辑###########################
{
design <- model.matrix(~metadata$group)
dge <- DGEList(counts=expr)
keep <- filterByExpr(dge, design)
dge <- dge[keep,,keep.lib.sizes=FALSE]
dge <- calcNormFactors(dge)
logCPM <- cpm(dge, log=TRUE, prior.count=3)
fit <- lmFit(logCPM, design)
fit <- eBayes(fit, trend=TRUE)
deg <- topTreat(fit, coef=ncol(design),n = Inf) |>
rownames_to_column("symbol")|>
select(symbol,log2FoldChange=logFC,pvalue=P.Value,padj=adj.P.Val)
}
### deg结果的命名规范必须是如下,以提供给volcano和heatmap函数使用
#symbol baseMean log2FoldChange lfcSE stat pvalue padj
#hsa-let-7a 1.444046e+03 0.0902414404 0.2895802 0.3116284873 0.75532288 0.9997432
##################limma的逻辑###########################
if(name %in% names(obj@DegDFs)){
obj@DegDFs[[name]] <- new("DegDF",expr=expr,metadata=metadata,deg=deg)
# obj@DegDFs <- c(obj@DegDFs,DegDF_list)
}else{
DegDF_list <- list(new("DegDF",expr=expr,metadata=metadata,deg=deg))
names(DegDF_list) <- name
obj@DegDFs <- c(obj@DegDFs,DegDF_list)
}
obj
})
miRNA_Obj <-runDeg(miRNA_Obj,
name="miRNA_SCRAMBLE_vs_2558_RWP1",
treatment=c("2558-SCRAMBLE","RWP1-SCRAMBLE"),
control=c(miRNA_Obj@group$cell_2558,miRNA_Obj@group$cell_RWP1),
treatment_name="SCRAMBLE",
control_name="2558&RWP1")
miRNA_Obj <- volcano(miRNA_Obj,name="miRNA_SCRAMBLE_vs_2558_RWP1")
miRNA_Obj <- intersectGene(miRNA_Obj)
setMethod("intersectGene","YQS136",function(obj){
gene_list <- lapply(1:length(obj@DegDFs),function(x){obj@DegDFs[[x]]@degSig$symbol})
names(gene_list) <- names(obj@DegDFs)
gene_list <- gene_list[lengths(gene_list) != 0]
obj@intersectGene <- Reduce(function(x,y) intersect(x,y), gene_list,accumulate =FALSE)
{
myCol <- brewer.pal(length(gene_list), "Set1")
res <- venn(gene_list, zcolor = myCol,box=F,opacity = 0.3)
#ggvenn( gene_list,stroke_size = 0.5, set_name_size = 3, text_size = 2)
}
obj
})
miRNA_Obj <- intersectGene(miRNA_Obj)
#### 函数调试方式1:给参数附上具体的值
metadata <- getMetadata(miRNA_Obj,
treatment=c("2558-SCRAMBLE","RWP1-SCRAMBLE"),
control=c(miRNA_Obj@group$cell_2558,miRNA_Obj@group$cell_RWP1),
treatment_name="SCRAMBLE",
control_name="2558&RWP1")
name <- "miRNA_SCRAMBLE_vs_2558_RWP1"
obj <- miRNA_Obj
#### 函数debug方式2:通过Debug的方式进行调试
#' Print method for "foo" class
#'
#' @param x An object of class "foo"
#' @param ... Other arguments passed to or from other methods
#'
#' @export print.foo
#' @export
print.foo <- function(x, ...) {
cat("This is just a dummy function.\n")
}
# Generated by roxygen2: do not edit by hand
S3method(print,foo)
export(print.foo)
https://stackoverflow.com/questions/18512528/how-to-export-s3-method-so-it-is-available-in-namespace
https://github.com/YuLab-SMU/DOSE/blob/master/R/accessor.R#L84
##' @method [[ enrichResult
##' @export
`[[.enrichResult` <- function(x, i) {
gc <- geneInCategory(x)
if (!i %in% names(gc))
stop("input term not found...")
gc[[i]]
}
stampedEnv <- setClass("stampedEnv", contains = "environment",
slots = c(update = "POSIXct"))
setMethod("[[<-", c("stampedEnv", "character", "missing"),
function(x, i, j, ..., value) {
ev <- as(x, "environment")
ev[[i]] <- value #update the object in the environment
x@update <- Sys.time() # and the update time
x})
e1 <- stampedEnv(update = Sys.time())
e1[["noise"]] <- rnorm(10)