as.data.frame(x)和as(x,“data.frame”)之间的区别

时间:2015-10-09 20:29:45

标签: r casting

我会保持简单。为什么这样做:

> as.data.frame(c('a', 'b'))
  c("a", "b")
1           a
2           b

但这不是:

> as(c('a', 'b'), "data.frame")
Error in as(c("a", "b"), "data.frame") : 
  no method or default for coercing “character” to “data.frame”

我认为后者只是以某种方式转换成前者,但我想不会。

2 个答案:

答案 0 :(得分:3)

也许R的作者认为复制第一种方法会鼓励糟糕的编码实践。第一个结果看起来并不特别值得模拟,因为列的名称不易使用。字符值的data.frame方法提供了更好的行为结果,因为它是使用有效名称创建的:

> as.data.frame(c('a','b'))
  c("a", "b")
1           a
2           b

data.frame(c('a','b'))
  c..a....b..
1           a
2           b

当您尝试使用该列的名称提取值时会发生什么。既然每个人都知道数据帧真的是列表对象,(对吧?)......那么期望编码人员使用list参数会更自然:

data.frame(list(b=c('a', 'b'))  )
  b
1 a
2 b

# same as
> as.data.frame(list(f=c('a','b')))
  f
1 a
2 b

Alex的回答指导您完成as - 功能代码,该代码详细阐述并确认了上面的joran评论。该函数不使用S3调度,而是查找已由包创建或使用setAs构造的注册强制方法,这是一种在构建S4方法时更常用的过程。

> setAs("character", "data.frame", function(from){ to=as.data.frame.character(from)})
> new=as(c('a', 'b'), "data.frame")
> new
  from
1    a
2    b

setAs功能还允许您在输入read.*时使用自定义强制功能 - How can I completely remove scientific notation for the entire R session

答案 1 :(得分:1)

我认为这与as不是通用函数的事实有关,例如:

R> mean
function (x, ...) 
UseMethod("mean")
<bytecode: 0x000000000a617ed0>
<environment: namespace:base>

由于它不是通用的,因此没有调用方法调度(即UseMethod

另一方面,as.data.frame是一个通用函数 - 请参阅methods(class= "data.frame")as.data.frame的来源

如果在as上有方法调度,那么您的假设&#34;后者将转换为前者&#34;会是对的。由于as不是通用函数,因此您的假设是错误的。

如果您查看as的源代码,您会发现它本质上是对许多if-else案例的调用,而不是对方法调度的调用。在第52行,您会看到返回错误的catch:

if (is.null(asMethod)) 
        stop(gettextf("no method or default for coercing %s to %s", 
                      dQuote(thisClass), dQuote(Class)), domain = NA)

这给出了你看到的回报。