R中的模式和类有什么区别?

Tri*_*tio 38 r

我正在学习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的面向对象的类层次结构.我很难找到这个图形化的布局,但我能找到的最好的是这个图:

rpy2 robjects包

(如果有人能指出我更准确的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禁止它在算术运算中使用.

实际上,除了在没有指定显式类时隐式定义类,模式的使用不是很多.


SHU*_*ANG 7

我希望以下示例有用.特别是,看看最后两个例子.

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()的情况.


sam*_*141 6

只是为了更好的可读性。

我希望下面的例子有帮助。特别是,看看最后两个例子。

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


alp*_*alp 5

简单地说,唯一真正有用的是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)


Tri*_*tio 0

经过多年的 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)\n

mode并且storage.mode是 R 的前身 S 语言的兼容性保留。storage.mode是低级数据类型,mode是稍高级的数据类型。但它们在 R 中实际上并没有什么用处,除非您同时与 R 和 S 代码进行交互,而我认识的人都没有这样做。所以,我不会进一步讨论它们。这里提到的四种类型中,只有classtypeof与当代 R 编程相关。

\n

typeof揭示了 R 对象最基本的数据类型,一直到实现 R 的底层 C 语言数据类型。因此,它指示变量如何按照 R 中可用的最低级别数据类型存储在计算机内存中。一个对象只能有一种typeof类型。不同的可能性可以从以下位置找到help(typeof)

\n
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)\n

class主要是指从R的S3面向对象系统角度来看的数据类型。(我刚刚了解到,R 历史上至少有九种不同的面向对象系统;从 S 继承的 S3 是最普遍使用的。)根据我目前的理解,类型是typeof对象本质的基础,而class类型是一种用于描述对象的标签。两者之间的主要区别在于,前者typeof是只读,后者class是读写。也就是说,我们不能直接改变对象的typeof类型;我们必须将底层对象转换为不同类型的对象;事实上,不允许对 进行赋值typeof。相反,class允许赋值,对于基本数据类型,将变量从一种数据类型转换为另一种数据类型。typeof因此,可以通过更改变量来间接转换变量来更改变量class

\n
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类型。那么,让我们尝试一些有趣的事情:

\n
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)\n

typeof此示例显示了和之间的一些关键区别class

\n
    \n
  • 一个对象可能只有一种typeof类型,但也可能有多个class类。
  • \n
  • 而 istypeof是对象的基础,class只不过是一种属性(尽管是特殊的属性)。
  • \n
  • class类可以是我们想要的任何内容,无论typeof是否有效类型(例如,示例中的“mango”)。
  • \n
  • 如果一个对象被分配了多个class有效类型的类,那么根据类型层次结构,typeof最基本的一个类就是用于其真实类型的类typeoftypeof类型的类。
  • \n
  • 内置is.*函数与类型相对应typeof,而不是直接与class. 因此,我们不能误is.character()认为我们的操纵变量是一个字符向量。最终版本的字符class只是一个属性标签,而不是typeof对象的真实类型。
  • \n
\n