如果在带有字符和数字列的data.frame上使用apply over rows,则apply会在内部使用as.matrix将data.frame转换为仅字符 . 但如果数字列由不同长度的数字组成,则.matrix会添加空格以匹配最高/“最长”数字 .
一个例子:
df <- data.frame(id1=c(rep("a",3)),id2=c(100,90,8), stringsAsFactors = FALSE)
df
## id1 id2
## 1 a 100
## 2 a 90
## 3 a 8
as.matrix(df)
## id1 id2
## [1,] "a" "100"
## [2,] "a" " 90"
## [3,] "a" " 8"
我原以为结果是:
id1 id2
[1,] "a" "100"
[2,] "a" "90"
[3,] "a" "8"
为什么多余的空间?
在data.frame上使用apply时,它们可能会产生意外的结果:
myfunc <- function(row){
paste(row[1], row[2], sep = "")
}
> apply(df, 1, myfunc)
[1] "a100" "a 90" "a 8"
>
虽然循环给出了预期的结果 .
> for (i in 1:nrow(df)){
print(myfunc(df[i,]))
}
[1] "a100"
[1] "a90"
[1] "a8"
和
> paste(df[,1], df[,2], sep = "")
[1] "a100" "a90" "a8"
是否有任何情况下使用as.matrix添加的额外空格是有用的?
5 回答
这是因为在
as.matrix.data.frame
方法中转换非数字数据的方式 . 有一个简单的解决方法,如下所示 .详情
?as.matrix
注意到转换是通过format()
完成的,并且在这里添加了额外的空格 . 具体来说,?as.matrix
在 Details 部分中有这个:?format
也注意到了考虑这个示例来说明行为
format
不必以这种方式工作,因为它具有trim
:例如
但是没有办法将这个参数传递给
as.matrix.data.frame
方法 .解决方法
解决此问题的方法是通过
sapply
手动自己应用format()
. 在那里你可以通过trim = TRUE
或者,使用
vapply
,我们可以说明我们期望返回的内容(这里是长度为3 [nrow(df)
]的字符向量):这看起来有点奇怪 . 在手册(
?as.matrix
)中,它解释了format
被调用以转换为字符矩阵:你可以看到,如果直接调用
format
,它会执行as.matrix
所做的事情:你需要做的是通过
trim
arugment:但是,不幸的是,
as.matrix.data.frame
函数不允许你这样做 .所以,你可以修改
as.data.frame.matrix
. 但是,我认为这将是一个很好的功能添加,但是,将它包含在基础中 .但是,一个快速的解决方案就是:
as.matrix
内部调用format
:这就是额外空间的来源 .
format
有一个额外的参数trim
来删除那些:但是,您无法将此参数提供给
as.matrix
.之前的答案已经解释了这种行为的原因,但我想提供另一种规避这种做法的方法:
请注意,如果使用
stringsAsFactors = TRUE
,则无法将因子级别转换为数字 .只是另一个解决方案:如果你不介意下载软件包,trimWhiteSpace(x)(来自limma R pckg)也可以完成这项工作 .