首页 文章详情

R变量索引 - 什么时候使用 @或$

生信宝典 | 39 2022-07-04 13:17 0 0 0
UniSMS (合一短信)

单细胞分析经常用到Seurat包,整个分析过程中的中间结果都在一个Seurat对象中存储。常需要从里面提取对应数据进行后续分析,有时会用$,有时会用@,怎么选择呢?

str函数是我们的好帮手,清晰展示对象层级结构和索引方式,如下,对应名字前出现@则用@索引(比如pbmc@assays),有$则用$索引(如pbmc@assays$RNA)。

>str(pbmc)
Formal class 'Seurat' [package "Seurat"] with 12 slots
..@ assays :List of 1
.. ..$ RNA:Formal class 'Assay' [package "Seurat"] with 7 slots
.. .. .. ..@ counts :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
.. .. .. .. .. ..@ i : int [1:2282976] 29 73 80 148 163 184 186 227 229 230 ...
.. .. .. .. .. ..@ p : int [1:2701] 0 779 2131 3260 4220 4741 5522 6304 7094 7626 ...
.. .. .. .. .. ..@ Dim : int [1:2] 13714 2700
.. .. .. .. .. ..@ Dimnames:List of 2
.. .. .. .. .. .. ..$ : chr [1:13714] "AL627309.1" "AP006222.2" "RP11-206L10.2" "RP11-206L10.9" ...
.. .. .. .. .. .. ..$ : chr [1:2700] "AAACATACAACCAC" "AAACATTGAGCTAC" "AAACATTGATCAGC" "AAACCGTGCTTCCG" ...
.. .. .. .. .. ..@ x : num [1:2282976] 1 1 2 1 1 1 1 41 1 1 ...
.. .. .. .. .. ..@ factors : list()
.. .. .. ..@ data :Formal class 'dgCMatrix' [package "Matrix"] with 6 slots
.. .. .. .. .. ..@ i : int [1:2282976] 29 73 80 148 163 184 186 227 229 230 ...
.. .. .. .. .. ..@ p : int [1:2701] 0 779 2131 3260 4220 4741 5522 6304 7094 7626 ...
.. .. .. .. .. ..@ Dim : int [1:2] 13714 2700
.. .. .. .. .. ..@ Dimnames:List of 2
.. .. .. .. .. .. ..$ : chr [1:13714] "AL627309.1" "AP006222.2" "RP11-206L10.2" "RP11-206L10.9" ...
.. .. .. .. .. .. ..$ : chr [1:2700] "AAACATACAACCAC" "AAACATTGAGCTAC" "AAACATTGATCAGC" "AAACCGTGCTTCCG" ...
.. .. .. .. .. ..@ x : num [1:2282976] 1 1 2 1 1 1 1 41 1 1 ...
.. .. .. .. .. ..@ factors : list()
.. .. .. ..@ scale.data : num[0 , 0 ]
.. .. .. ..@ key : chr "rna_"
.. .. .. ..@ var.features : logi(0)
.. .. .. ..@ meta.features:'data.frame': 13714 obs. of 0 variables
.. .. .. ..@ misc : NULL
..@ meta.data :'data.frame': 2700 obs. of 7 variables:
.. ..$ orig.ident : Factor w/ 1 level "YSX": 1 1 1 1 1 1 1 1 1 1 ...
.. ..$ nCount_RNA : num [1:2700] 2419 4903 3147 2639 980 ...
.. ..$ nFeature_RNA: int [1:2700] 779 1352 1129 960 521 781 782 790 532 550 ...
.. ..$ phases : Factor w/ 3 levels "G1","G2M","S": 1 1 1 1 3 1 1 1 1 1 ...
.. ..$ G1 : num [1:2700] 0.988 0.568 0.999 0.941 0.432 0.966 0.997 0.95 0.703 0.993 ...
.. ..$ S : num [1:2700] 0.216 0.692 0.415 0.091 0.302 0.082 0.034 0.175 0.167 0.004 ...
.. ..$ G2M : num [1:2700] 0.002 0.055 0.001 0.079 0.227 0.055 0.274 0.301 0.273 0.333 ...
..@ active.assay: chr "RNA"
..@ active.ident: Factor w/ 1 level "YSX": 1 1 1 1 1 1 1 1 1 1 ...
..@ project.name: chr "YSX"

具体操作如下:

# 查看metadata文件列信息
> colnames(pbmc@meta.data)
[1] "orig.ident" "nCount_RNA" "nFeature_RNA" "phases" "G1" "S" "G2M"

# 查看部分基因在部分细胞的原始reads counts
> pbmc@assays$RNA@counts[11:14,1:30]
Assay data with 13714 features for 2700 cells
First 10 features:
AL627309.1, AP006222.2, RP11-206L10.2, RP11-206L10.9, LINC00115, NOC2L,
KLHL17, PLEKHN1, RP11-54O7.17, HES4

那么$@,到底是什么?有什么区别呢?

首先这两个符号最大的区别在于:它们是两个不同的面向对象系统的提取变量的符号。S3对象通常是列表,使用$索引;S4对象的不同slot使用@索引

那什么是S3、S4呢?

要想知道S3、S4,首先得了解一下面向对象编程(object-oriented programming),它是一种编程范式,它将对象作为程序的基本单元, 将程序和数据封装 (encapsulate) 其中, 以提高软件的重用性, 灵活性和扩展性。

R语言中现有的S3类、S4类、以及R6类等都可以实现面向对象的编程范式。

与S3不同,S4有更正式的定义和创建对象的统一方法。

如何定义S4类?

S4类使用setClass()函数来定义

用R的术语来说,成员变量被称为属性。当定义一个类时,我们需要设置类的名字和成员变量(以及成员变量的属性)。每个成员变量也会称为一个slot

例子一:定义S4类

setClass("student", slots=list(name="character", age="numeric", GPA="numeric"))

在上面的例子中,我们定义了一个名为student的新类,它有三个slot,分别是name (字符型), ageGPA (数值型)。

如何创建S4对象?

S4类使用new()函数来定义

例子二:创建S4对象

# create an object using new()
# provide the class name and value for slots
s <- new("student",name="John", age=21, GPA=3.5)
s
An object of class "student"
Slot "name":
[1] "John"
Slot "age":
[1] 21
Slot "GPA":
[1] 3.5

函数setClass()返回一个生成器函数。

这个生成器函数(通常与类同名)可用于创建新对象,它充当构造器。

> student <- setClass("student", slots=list(name="character", age="numeric", GPA="numeric"))
> student
class generator function for class “student” from package ‘.GlobalEnv’
function (...)
new("student", ...)

现在我们可以用构造函数创建新对象。

例子三:用构造函数创建S4对象

> student(name="John", age=21, GPA=3.5)
An object of class "student"
Slot "name":
[1] "John"
Slot "age":
[1] 21
Slot "GPA":
[1] 3.5

如何访问和修改属性?

正如使用$访问list表的组件一样,使用@访问对象的属性。

访问属性

s@name
[1] "John"
s@GPA
[1] 3.5
s@age
[1] 21

直接修改属性

可以通过直接赋值修改属性

# modify GPA
s@GPA <- 3.7
s
An object of class "student"
Slot "name":
[1] "John"
Slot "age":
[1] 21
Slot "GPA":
[1] 3.7

slot()函数修改属性

> slot(s,"name")
[1] "John"
> slot(s,"name") <- "Paul"
> s
An object of class "student"
Slot "name":
[1] "Paul"
Slot "age":
[1] 21
Slot "GPA":
[1] 3.7

方法和泛型函数

与S3类一样,S4类的方法也属于泛型函数,而不是类本身。使用S4泛型与S3泛型非常相似。

可以使用showMethods()函数列出所有可用的S4通用函数和方法。

例子四:列出所有泛型函数

> showMethods()
Function: - (package base)
Function: != (package base)
...
Function: trigamma (package base)
Function: trunc (package base)

在交互模式中输入对象名称将会输出它,用S4通用函数show()来达到同样效果。

您可以在上面的列表中看到这个函数,这个函数类似于S3 print()函数。

例子五:判断一个函数是否是泛型函数。

> isS4(print)
[1] FALSE
> isS4(show)
[1] TRUE

我们可以使用showMethods(show)列出show泛型函数所有的方法。

例子六:列出泛型函数的所有方法。

> showMethods(show)
Function: show (package methods)
object="ANY"
object="classGeneratorFunction"
...
object="standardGeneric"
(inherited from: object="genericFunction")
object="traceable"

如何去写你自己的方法?

我们可以使用setMethod()帮助函数写自己的方法。

例如,我们可以实现show()泛型的类方法,如下所示。

setMethod("show",
"student",
function(object) {
cat(object@name, "\n")
cat(object@age, "years old\n")
cat("GPA:", object@GPA, "\n")
}
)

现在,如果我们像以前一样以交互模式写出对象的名称,就会执行上面的代码。

参考来源


https://www.datamentor.io/r-programming/s4-class/

R统计和作图

高颜值免费在线绘图


往期精品

画图三字经 生信视频 生信系列教程 

心得体会 TCGA数据库 Linux Python 

高通量分析 免费在线画图 测序历史 超级增强子

生信学习视频 PPT EXCEL 文章写作 ggplot2

海哥组学 可视化套路 基因组浏览器

色彩搭配 图形排版 互作网络

自学生信 2019影响因子 GSEA 单细胞 

后台回复“生信宝典福利第一波”或点击阅读原文获取教程合集



good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter