我正在学习R(我本周才开始),我一直在努力学习typeof,mode,storage.mode和class的概念.我一直在上下搜索(官方R文档,StackOverflow,谷歌等),我无法找到任何明确的解释这些之间的区别.(一些StackOverflow 和 CrossValidated答案并没有真正帮助我解决问题.)最后(我希望),我想我明白了,所以我的问题是验证我的理解是否正确.
mode vs storage.mode: mode和storage.mode基本相同,除了处理"单一"数据类型的微小差别.
mode vs typeof: 非常相似,除了一些差异,最值得注意的是两者(typeof"integer"和"double")=(mode"numeric"); 两者(typeof"special"和"builtin"=(mode"function").
class: Class基于R的面向对象的类层次结构.我很难找到这个图形化的布局,但我能找到的最好的是这个图:
(如果有人能指出我更准确的R类层次结构,我会替换它.)
虽然类名与R class()函数的结果不完全对应,但我认为层次结构基本上是准确的.我的理解是对象的"类" - 即class()函数的结果 - 是层次结构中的根类.因此,例如,"Vector"不是根类,因此它永远不会显示为class()函数的结果.根类可能更像是"StrVector"("字符")或"BoolVector"("逻辑").相比之下,"矩阵"本身就是一个根类; 因此,它的类是"矩阵".
显然,R支持多重继承,因此一些对象可以有多个类.
typeof/mode/storage.mode vs class:这是我最难理解的部分.我现在的理解是:typeof/mode/storage.mode(我将其称之为"模式")基本上是R对象可以作为其值之一保存的最复杂的数据类型.因此,例如,由于矩阵,数组和向量只能包含一个向量数据类型,因此它们的模式(即它们可以容纳的最复杂的数据类型)通常是数字,字符或逻辑,即使它们的类(它们在类中的位置)等级)是完全不同的东西.
这最有趣的地方(也就是混乱)就像列表这样的对象."列表"模式意味着对象中的每个值本身可以是一个列表(即,可以包含不同数据类型的对象).因此,无论类本身是否为"列表",都有多个对象(例如数据帧)可以包含不同的值,因此其模式是"列表",即使它们的类是其他的.
总而言之,我的理解是:
typeof/mode/storage.mode(几乎相同的东西)基本上是R对象可以作为其值之一保存的最复杂的数据类型; 而
class是根据R类层次结构的对象的面向对象分类.
我的理解准确吗?如果没有,有人可以给出更准确的解释吗?
Tri*_*k M 18
'mode'是根据对象的基本结构互斥的对象分类."原子"模式是数字,复杂,字符和逻辑.递归对象具有诸如"列表"或"功能"之类的模式或其他一些模式.对象只有一种模式.
'class'是分配给对象的属性,用于确定泛型函数如何对其进行操作.它不是互斥的分类.如果一个对象没有分配给它的特定类,例如一个简单的数字向量,它的类通常与它的模式相同,按照惯例.
改变对象的模式通常被称为"强制".对象的模式可以在不必改变类的情况下改变.例如
> x <- 1:16
> mode(x)
[1] "numeric"
> dim(x) <- c(4,4)
> mode(x)
[1] "numeric"
> class(x)
[1] "matrix"
> is.numeric(x)
[1] TRUE
> mode(x) <- "character"
> mode(x)
[1] "character"
> class(x)
[1] "matrix"
Run Code Online (Sandbox Code Playgroud)
然而:
> x <- factor(x)
> class(x)
[1] "factor"
> mode(x)
[1] "numeric"
Run Code Online (Sandbox Code Playgroud)
在这个阶段,即使x
再次使用模式数字,它的新类也
factor
禁止它在算术运算中使用.
实际上,除了在没有指定显式类时隐式定义类,模式的使用不是很多.
我希望以下示例有用.特别是,看看最后两个例子.
x <- 1L
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- 1
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- letters
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- TRUE
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- cars
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- cars[1]
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- cars[[1]]
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- matrix(cars)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- new.env()
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- expression(1 + 1)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- quote(y <- 1 + 1)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
x <- ls
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
Run Code Online (Sandbox Code Playgroud)
结果是
[1] "integer" "numeric" "integer" "integer"
[1] "numeric" "numeric" "double" "double"
[1] "character" "character" "character" "character"
[1] "logical" "logical" "logical" "logical"
[1] "data.frame" "list" "list" "list"
[1] "data.frame" "list" "list" "list"
[1] "numeric" "numeric" "double" "double"
[1] "matrix" "list" "list" "list"
[1] "environment" "environment" "environment" "environment"
[1] "expression" "expression" "expression" "expression"
[1] "<-" "call" "language" "language"
[1] "function" "function" "function" "closure"
Run Code Online (Sandbox Code Playgroud)
最后一个示例显示了typeof()!= storage.mode()的情况.
只是为了更好的可读性。
我希望下面的例子有帮助。特别是,看看最后两个例子。
x <- 1L
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "integer" "numeric" "integer" "integer"
x <- 1
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "numeric" "numeric" "double" "double"
x <- letters
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "character" "character" "character" "character"
x <- TRUE
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "logical" "logical" "logical" "logical"
x <- cars
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "data.frame" "list" "list" "list"
x <- cars[1]
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "data.frame" "list" "list" "list"
x <- cars[[1]]
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "numeric" "numeric" "double" "double"
x <- matrix(cars)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "matrix" "list" "list" "list"
x <- new.env()
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "environment" "environment" "environment" "environment"
x <- expression(1 + 1)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "expression" "expression" "expression" "expression"
x <- quote(y <- 1 + 1)
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "<-" "call" "language" "language"
x <- ls
print(c(class(x), mode(x), storage.mode(x), typeof(x)))
[1] "function" "function" "function" "closure"
Run Code Online (Sandbox Code Playgroud)
积分 - @Shuaicheng WANG
简单地说,唯一真正有用的是class()
和typeof()
class
可以被描述为一个对象的“容器”,一个使这个对象在外部行为的属性,函数将这个特定的对象“类型”作为参数
type
是这个对象在容器内部构成的,底层值的“类型”
很好的明显例子:
x <- as.Date('2010-01-01')
class(x) # Date
typeof(x) # double
unclass(x) # 14610
attr(x, 'tz') <- 'CEST'
attributes(x)$class # "Date"
attributes(x)$tz # "CEST"
Run Code Online (Sandbox Code Playgroud)
经过多年的 R 学习,我现在有足够的信心来回答八年前我在学习 R 的第一周时提出的这个问题!我目前正在学习 Richie Cotton 的 DataCamp 课程,内容是在 R 中使用 S3 和 R6 进行面向对象编程。他提供了一个可爱的例子,我在这里改编它来演示 R 中这四种“数据类型”之间的差异:
\n# objects of various datatypes\nlist(\n an_integer_vector = rpois(24, lambda = 5),\n a_numeric_vector = rbeta(24, shape1 = 1, shape2 = 1),\n an_integer_array = array(rbinom(24, size = 8, prob = 0.5), dim = c(2, 3, 4)),\n a_numeric_array = array(rweibull(24, shape = 1, scale = 1), dim = c(2, 3, 4)),\n a_data_frame = data.frame(int = rgeom(24, prob = 0.5), num = runif(24)),\n a_factor = factor(month.abb),\n a_formula = y ~ x,\n a_closure_function = mean,\n a_builtin_function = length,\n a_special_function = `if`\n) |> \n purrr::map(\\(.o) {\n c(\n class = class(.o), \n typeof = typeof(.o), \n mode = mode(.o), \n storage.mode = storage.mode(.o)\n )\n })\n#> $an_integer_vector\n#> class typeof mode storage.mode \n#> "integer" "integer" "numeric" "integer" \n#> \n#> $a_numeric_vector\n#> class typeof mode storage.mode \n#> "numeric" "double" "numeric" "double" \n#> \n#> $an_integer_array\n#> class typeof mode storage.mode \n#> "array" "integer" "numeric" "integer" \n#> \n#> $a_numeric_array\n#> class typeof mode storage.mode \n#> "array" "double" "numeric" "double" \n#> \n#> $a_data_frame\n#> class typeof mode storage.mode \n#> "data.frame" "list" "list" "list" \n#> \n#> $a_factor\n#> class typeof mode storage.mode \n#> "factor" "integer" "numeric" "integer" \n#> \n#> $a_formula\n#> class typeof mode storage.mode \n#> "formula" "language" "call" "language" \n#> \n#> $a_closure_function\n#> class typeof mode storage.mode \n#> "function" "closure" "function" "function" \n#> \n#> $a_builtin_function\n#> class typeof mode storage.mode \n#> "function" "builtin" "function" "function" \n#> \n#> $a_special_function\n#> class typeof mode storage.mode \n#> "function" "special" "function" "function"\n
Run Code Online (Sandbox Code Playgroud)\nmode
并且storage.mode
是 R 的前身 S 语言的兼容性保留。storage.mode
是低级数据类型,mode
是稍高级的数据类型。但它们在 R 中实际上并没有什么用处,除非您同时与 R 和 S 代码进行交互,而我认识的人都没有这样做。所以,我不会进一步讨论它们。这里提到的四种类型中,只有class
和typeof
与当代 R 编程相关。
typeof
揭示了 R 对象最基本的数据类型,一直到实现 R 的底层 C 语言数据类型。因此,它指示变量如何按照 R 中可用的最低级别数据类型存储在计算机内存中。一个对象只能有一种typeof
类型。不同的可能性可以从以下位置找到help(typeof)
:
A character string. The possible values are listed in the structure TypeTable\nin \xe2\x80\x98src/main/util.c\xe2\x80\x99. Current values are the vector types "logical", "integer", \n"double", "complex", "character", "raw" and "list", "NULL", "closure" \n(function), "special" and "builtin" (basic functions and operators), \n"environment", "S4" (some S4 objects) and others that are unlikely to be seen \nat user level ("symbol", "pairlist", "promise", "language", "char", "...", \n"any", "expression", "externalptr", "bytecode" and "weakref").\n
Run Code Online (Sandbox Code Playgroud)\nclass
主要是指从R的S3面向对象系统角度来看的数据类型。(我刚刚了解到,R 历史上至少有九种不同的面向对象系统;从 S 继承的 S3 是最普遍使用的。)根据我目前的理解,类型是typeof
对象本质的基础,而class
类型是一种用于描述对象的标签。两者之间的主要区别在于,前者typeof
是只读,后者class
是读写。也就是说,我们不能直接改变对象的typeof
类型;我们必须将底层对象转换为不同类型的对象;事实上,不允许对 进行赋值typeof
。相反,class
允许赋值,对于基本数据类型,将变量从一种数据类型转换为另一种数据类型。typeof
因此,可以通过更改变量来间接转换变量来更改变量class
:
some_numbers <- c(1L, 2L, 3L) # \'L\' added to create integers, not doubles\nsome_numbers\n#> [1] 1 2 3\ntypeof(some_numbers)\n#> [1] "integer"\nclass(some_numbers)\n#> [1] "integer"\n\ntypeof(some_numbers) <- \'double\'\n#> Error in typeof(some_numbers) <- "double": could not find function "typeof<-"\nclass(some_numbers) <- \'character\'\nsome_numbers\n#> [1] "1" "2" "3"\ntypeof(some_numbers)\n#> [1] "character"\nclass(some_numbers)\n#> [1] "character"\n
Run Code Online (Sandbox Code Playgroud)\n另一个重要的区别是一个对象可以有多个class
类,而它只能有一种typeof
类型。那么,让我们尝试一些有趣的事情:
some_numbers <- c(1L, 2L, 3L, 4L, 5L) # \'L\' added to create integers, not doubles\nsome_numbers\n#> [1] 1 2 3 4 5\ntypeof(some_numbers)\n#> [1] "integer"\nclass(some_numbers)\n#> [1] "integer"\n\nclass(some_numbers) <- c(\'mango\', \'character\', \'integer\')\nsome_numbers\n#> [1] 1 2 3 4 5\n#> attr(,"class")\n#> [1] "mango" "character" "integer"\ntypeof(some_numbers)\n#> [1] "integer"\nclass(some_numbers)\n#> [1] "mango" "character" "integer"\n\nis.integer(some_numbers)\n#> [1] TRUE\nis.character(some_numbers)\n#> [1] FALSE\n
Run Code Online (Sandbox Code Playgroud)\ntypeof
此示例显示了和之间的一些关键区别class
:
typeof
类型,但也可能有多个class
类。typeof
是对象的基础,class
只不过是一种属性(尽管是特殊的属性)。class
类可以是我们想要的任何内容,无论typeof
是否有效类型(例如,示例中的“mango”)。class
有效类型的类,那么根据类型层次结构,typeof
最基本的一个类就是用于其真实类型的类typeof
typeof
类型的类。is.*
函数与类型相对应typeof
,而不是直接与class
. 因此,我们不能误is.character()
认为我们的操纵变量是一个字符向量。最终版本的字符class
只是一个属性标签,而不是typeof
对象的真实类型。 归档时间: |
|
查看次数: |
15960 次 |
最近记录: |