Bug 15198 - Wishlist: improve printing of zero-length object of class 'table'
Wishlist: improve printing of zero-length object of class 'table'
Status: CLOSED FIXED
Product: R
Classification: Unclassified
Component: Wishlist
R 2.15.2
ix86 (32-bit) Windows 32-bit
: P5 enhancement
Assigned To: R-core
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2013-02-08 11:23 UTC by Suharto Anggono
Modified: 2013-02-12 15:54 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Suharto Anggono 2013-02-08 11:23:55 UTC
> table(NULL)
character(0)

Initially, the above made me believe that the result of table(NULL) was of mode character. So, I thought that function 'table' did wrong.

But ...

> str(table(NULL))
 'table' int[0 (1d)]
 - attr(*, "dimnames")=List of 1
  ..$ : NULL

So, the result of table(NULL) is, in fact, correct. It is just the printing.

I expect object of class 'table' to be printed just like usual array. In this case, the printing of usual array is like this, which is acceptable to me.

> unclass(table(NULL))
integer(0)

What happens is that 'print' method of class 'table' prints the result of 'format', and the result of 'format' is of mode character. The fix for 'print.table' may be, if 'x' is of length zero, skip processing and directly do print(unclass(x)).


The same thing happens for class 'Date', 'POSIXct' and 'POSIXlt', but maybe not as surprising as 'table'.

> as.Date(character(0))
character(0)
> as.POSIXct(character(0))
character(0)
> as.POSIXlt(character(0))
character(0)


As an aside, I also have an issue about printing of usual zero-extent array.

The following is OK.

> array(integer(0), c(0,0))
<0 x 0 matrix>

The following is still OK.

> array(integer(0), c(0,0,2))
, , 1



, , 2



But, each of the following don't print anything. Each has zero as the last dimension. I say in my mind, "Where is the result?"

> array(integer(0), c(0,0,0))
> array(integer(0), c(0,2,0))
> array(integer(0), c(3,2,0))


> sessionInfo()
R version 2.15.2 (2012-10-26)
Platform: i386-w64-mingw32/i386 (32-bit)

locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base
Comment 1 Duncan Murdoch 2013-02-10 20:36:15 UTC
It's generally true in R that you can't trust print() to reveal the internal structure of an object.  So you'll need to make a case that this comes up in some case where it would mislead someone, and I just can't think of one.
Comment 2 Suharto Anggono 2013-02-11 12:13:35 UTC
(In reply to comment #1)
> It's generally true in R that you can't trust print() to reveal the internal
> structure of an object.  So you'll need to make a case that this comes up in
> some case where it would mislead someone, and I just can't think of one.

As indicated in my description, I was actually got fooled by the printing. But it's probably not a strong case. Having known that it is just display, it is no longer a problem for me now. But, this is the story.

Initially, I effectively executed table(NULL) by accident. NULL was the result of accessing a non-existing column (by $) in a data frame, that was imported from a table in database. It was my fault not to query the column names first (e.g. by calling names()) or to use completion on $.

Then, after realizing that I effectively executed table(NULL), seeing character(0) in the display made me wonder if function 'table' did wrong. It was the first time I see it (I used 'table' not often, not much). Usually, I saw that the result of 'table' was printed like usual array. I couldn't accept that the result was, I thought, of mode character. I checked the code of function 'table', didn't see something wrong.

Then, I tried
structure(integer(), class="table")
Seeing the same display made me think that something was wrong in class assignment.
I tried class "data.frame" and got a display indicating data frame, OK.
I tried class "a", got OK.
I tried x[0] for x an object of class 'Date', 'POSIXct', or 'POSIXlt'. Seeing character(0) in the display made me wonder, what was wrong. I never worked with empty 'Date', 'POSIXct', or 'POSIXlt' before. Seeing many times that a 'Date', 'POSIXct', or 'POSIXlt' object was displayed with quotes, like character vector, didn't make me realize that the display would shrink to character(0). My thinking was too far, that it was wrong for "known" class, somehow "registered" by R. I thought that making empty with class somehow "corrupted" the internal structure, so that it was recognized as of mode character.
But, how stupid I was, I didn't think of trying 'unclass' or 'str' or 'class'.

It took me a while before I looked at 'print.table'. Seeing what was going on there, I tried
print.default(table(NULL))
Only then, I tried 'unclass', 'str'.
Comment 3 Peter Dalgaard 2013-02-11 14:20:59 UTC
This also happens via table(NA) and similar cases. That would seem to be something that could fairly easily happen to and confuse beginners, and we're not really consistent across the number of extents:

> table(NA)
character(0)
> table(NA,NA)
<0 x 0 matrix>
> table(NA,NA,NA)
> table(NA,NA,1)
, ,  = 1


>


How about adding something like this at the beginning of print.table?

d <- dim(x) 
if (any(d==0)) {
  cat ("< table of extent", paste(d, collapse=" x "), ">\n")
  return ( invisible(x) )
}
Comment 4 Peter Dalgaard 2013-02-12 15:54:39 UTC
The suggested change has been made to R-devel.