Reputation: 385
I'll keep it simple. Why does this work:
> as.data.frame(c('a', 'b'))
c("a", "b")
1 a
2 b
But this doesn't:
> as(c('a', 'b'), "data.frame")
Error in as(c("a", "b"), "data.frame") :
no method or default for coercing “character” to “data.frame”
I assumed that the latter would simply somehow convert into the former, but I suppose not.
Upvotes: 1
Views: 397
Reputation: 263411
Maybe the R authors thought replicating the first method would be encouraging bad coding practice. The first result does not look particularly worth emulating because the name of the column will not be easy to use. The data.frame
method for character values delivers a much better behaved result since it gets created with a valid name:
> 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
See what happens when you try to extract values with the name of that column. Since everyone knows that dataframes are really list objects, (right?)... then it would be more natural to expect coders to use a list argument:
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's answer directs you to the as
-function code, which elaborates and confirms joran's comment above. That function doesn't use the S3 dispatch, but rather looks up registered coercion methods that have been created by packages or constructed with setAs
which is a process that is more commonly used in building S4-methods.
> 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
The setAs
function also allows you to use custom coercion at the time of input with the read.*
-functions: How can I completely remove scientific notation for the entire R session
Upvotes: 3
Reputation: 4907
I believe that it has to do with the fact that as
is not a generic function, such as mean:
R> mean
function (x, ...)
UseMethod("mean")
<bytecode: 0x000000000a617ed0>
<environment: namespace:base>
Since it's not a generic, there is no call to method dispatch (ie UseMethod
)
On the other hand, as.data.frame
is a generic function-- see methods(class= "data.frame")
or the source for as.data.frame
If there was method dispatch on as
, your assumption "that the latter would convert to the former" would be correct. Since as
is not a generic function, your assumption is wrong.
If you look at the source code to as
, you see that it's essentially a call to a number of if-else cases instead of a call to method dispatch. On line 52, you see the catch that returns your error:
if (is.null(asMethod))
stop(gettextf("no method or default for coercing %s to %s",
dQuote(thisClass), dQuote(Class)), domain = NA)
Which gives the return that you see.
Upvotes: 1