在对每一列调用函数之前,该apply()
函数将其第一个参数强制转换为矩阵。因此,您的数据框被强制转换为矩阵对象。该转换的结果是as.matrix(df_AB)
具有非空行名,而as.matrix(df_ab)
没有:
> str(as.matrix(df_ab))
int [1:5, 1:2] 1 2 3 4 5 6 5 4 3 2
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:2] "a" "b"
> str(as.matrix(df_AB))
int [1:5, 1:2] 1 2 3 4 5 6 5 4 3 2
- attr(*, "dimnames")=List of 2
..$ : chr [1:5] "1" "2" "3" "4" ...
..$ : chr [1:2] "a" "b"
因此,当您apply()
对 的一列进行子集化时df_AB
,您会得到一个命名向量,它与未命名向量不同。
apply(df_AB, 2, str)
Named int [1:5] 1 2 3 4 5
- attr(*, "names")= chr [1:5] "1" "2" "3" "4" ...
Named int [1:5] 6 5 4 3 2
- attr(*, "names")= chr [1:5] "1" "2" "3" "4" ...
NULL
将其与函数进行对比,该subset()
函数使用逻辑向量作为 的值来选择行i
。并且看起来像子集一个具有非缺失值的 data.framei
会导致row.names
属性中的这种差异:
> str(as.matrix(df[1:5, 1:2]))
int [1:5, 1:2] 1 2 3 4 5 6 5 4 3 2
- attr(*, "dimnames")=List of 2
..$ : chr [1:5] "1" "2" "3" "4" ...
..$ : chr [1:2] "a" "b"
> str(as.matrix(df[, 1:2]))
int [1:5, 1:2] 1 2 3 4 5 6 5 4 3 2
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:2] "a" "b"
.Internal(inspect(x))
您可以使用该函数查看 data.frames 之间差异的所有血腥细节。有兴趣的可以自己看看。
正如 Roland 在他的评论中指出的那样,您可以使用该.row_names_info()
函数仅查看行名称的差异。
请注意,当i
缺失时,结果.row_names_info()
为负数,但如果您使用非缺失的子集,则结果为正数i
。
> .row_names_info(df_ab, type=1)
[1] -5
> .row_names_info(df_AB, type=1)
[1] 5
这些值的含义在以下内容中进行了解释?.row_names_info
:
type: integer. Currently ‘type = 0’ returns the internal
‘"row.names"’ attribute (possibly ‘NULL’), ‘type = 2’ the
number of rows implied by the attribute, and ‘type = 1’ the
latter with a negative sign for ‘automatic’ row names.