为什么可以使用 "$" 来对 SpatialPolygonsDataFrame 进行子集操作?

3

当我有一个SpatialPolygonsDataFrame对象时,我知道我可以通过两种方式获取数据:

spatial_df@data$column
spatial_df$column

然而,我不明白第二种方法为什么可行。我认为我必须使用@来访问data插槽?这是关于SpatialPolygonsDataFrame类的独特之处,还是关于S4对象的一般性问题?
可能的答案在sp文档中提供了。其中提到了SpatialPolygonsDataFrame类的[方法。然而,由于$等价于[[,而非[,我不确定那是否就是答案。

请再多阅读一些相关内容,其中应包括包含搜索词“S4”和“S3”的文章和博客。您对 $ 的结论是不正确的,或者至少是不完整的。请具体查看 ?"[" - IRTFM
我的理解来自于Hadley的Advanced R书籍中的内容。引用:“$是一个简写操作符,其中x$y等同于x[["y", exact = FALSE]]”。 - Heisenberg
是的。请注意第二部分。正如我所说的,“不完整”。关键点在于,"y"将不会被评估,而如果您将名称和对象作为第二个参数放入其中,它将被评估,该值而不是名称将成为结果的基础。 - IRTFM
@BondedDust 所以我已经找到了下面的答案。如果我没有错的话,$的行为方式是由于sp包内部实现的原因,而与S4无关。但是,您确实建议我更多地了解S4和S3的一般情况,所以我担心我仍然可能会犯错。 - Heisenberg
1个回答

6
简短回答是,$的这种行为是由sp包中的Spatial类实现的,并不是一般S4对象的特性。
详细回答(我是如何发现的):
- 使用showMethods("$")查找通用$的所有方法。
The result shows:
Function: $ (package base)
x="C++Class"
x="envRefClass"
x="Module"
x="Raster"
x="refObjectGenerator"
x="Spatial"
x="SpatialGDAL"
x="SpatialPoints"
x="SpatialPolygonsDataFrame"
    (inherited from: x="Spatial")

我们知道SpatialPolygonsDataFrame-classSpatial-class继承了$。我们可以通过以下方式进入根目录:

  • getMethod("$", "Spatial"),它展示了Spatial-class$实现如下:
Method Definition:

function (x, name) 
{
    if (!("data" %in% slotNames(x))) 
        stop("no $ method for object without attributes")
    x@data[[name]]
}
<environment: namespace:sp>
因此,spatial_df$col_namespatial_df@data[["col_name"]]的快捷方式。

这意味着spatial_df是一个S4对象,但它的一个节点,名为“data”的节点,其内容是一个S3风格的列表。$方法的定义基本上与通常的$方法相同,即[[name]] - IRTFM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接