I Ho
I Ho

Reputation: 157

Error when using pander on a data.table created with data.table::dcast

this is more a question of interest, as I found a work-around, although I don't find it pretty.

When I updated the pander package (to 0.6.1) an error started to occure whenever I try to to use pander() on a data.table in wide format that was constructed from a data.table (package version 1.10.4-3 or older) in long format using data.table::dcast():

Error in data.table::setattr(x, "row.names", row.names.dt) : row names must be 'character' or 'integer', not 'double'

I tried to remove any row names, but to no avail. After some research, I found out that with reshape2::dcast there is no error, but reshape2::dcast transforms the data.table in a data.frame, which isn't something I want. Of course I could transform the data.frame back into a data.table.

Here is some sample code that produces the error for me:

library(pander)
library(data.table)

dt.long <- data.table(time=c(1, 1, 2, 2), T=c("c", "t", "c", "t"), count=c(10, 15, 15, 20))
pander(dt.long) # this works fine

dt.wide <- dcast(dt.long, time~T, value.var = "count")
row.names(dt.wide) <- NULL # doesn't help
row.names(dt.wide) <- c() # doesn't help either
pander(dt.wide) # produces error

# work-around
library(reshape2)
dt.wide <- dcast(dt.long, time~T, value.var = "count")
pander(dt.wide) # works fine
class(dt.wide) # but this is a data.frame
dt.wide <- data.table(dt.wide) # now it is a data.table again

Is there a simple way to keep the data as data.table and use pander as it worked before?
I use R version 3.3.2, in case this matters.

Thank you in advance!

Upvotes: 1

Views: 346

Answers (2)

Uwe
Uwe

Reputation: 42544

Besides the obvious workaround to coerce dt.wide to data.frame in the call to pander() (dt.wide remains unchanged)

pander(as.data.frame(dt.wide))
----------------
 time   c    t  
------ ---- ----
  1     10   15 

  2     15   20 
----------------

the data.table method of pander() has a keys.as.row.names parameter (see ?pander.data.table). This parameter is TRUE by default.

So, another workaround is to set this parameter to FALSE:

pander(dt.wide, keys.as.row.names = FALSE)
----------------
 time   c    t  
------ ---- ----
  1     10   15 

  2     15   20 
----------------

However, I believe there is a bug in pander() as dt.wide is not keyed. It just has the sorted attribute set to time:

str(dt.wide)
Classes ‘data.table’ and 'data.frame':    2 obs. of  3 variables:
 $ time: num  1 2
 $ c   : num  10 15
 $ t   : num  15 20
 - attr(*, ".internal.selfref")=<externalptr> 
 - attr(*, "sorted")= chr "time"

Note that if column time is defined as integer, pander(dt.wide) doesn't throw an error but is omitting the time column from the result. (See GitHub issue).

Upvotes: 0

akrun
akrun

Reputation: 886978

It is the additional attributes that creates the problem. Set the 'sorted' attr to 'NULL' and it should work

dt.wide <- dcast(dt.long, time~T, value.var = "count")
attr(dt.wide, "sorted") <- NULL

Or use setattr

setattr(dt.wide, 'sorted', NULL)
pander(dt.wide)
#----------------
# time   c    t  
#------ ---- ----
#  1     10   15 

#  2     15   20 
#----------------

Upvotes: 1

Related Questions