From m@ech|er @end|ng |rom @t@t@m@th@ethz@ch  Wed Sep 18 10:35:42 2019
From: m@ech|er @end|ng |rom @t@t@m@th@ethz@ch (Martin Maechler)
Date: Wed, 18 Sep 2019 10:35:42 +0200
Subject: [Rd] '==' operator: inconsistency in data.frame(...) == NULL
In-Reply-To: <94e5fbbe-6f03-9b69-8abf-ebeced33a016@mpiib-berlin.mpg.de>
References: <9075d086-7945-b759-f311-765d626b7a61@mpiib-berlin.mpg.de>
 <23928.43189.410927.15494@stat.math.ethz.ch>
 <c21fa68d-00da-dcc1-6390-dce52c889748@mpiib-berlin.mpg.de>
 <f144303d-0fa6-7827-bca3-2587a43c3484@mpiib-berlin.mpg.de>
 <1bbabc36-43c8-aad6-4a08-b310d13c8938@mpiib-berlin.mpg.de>
 <94e5fbbe-6f03-9b69-8abf-ebeced33a016@mpiib-berlin.mpg.de>
Message-ID: <23937.60510.182530.176708@stat.math.ethz.ch>

>>>>> Hilmar Berger 
>>>>>     on Sat, 14 Sep 2019 13:31:27 +0200 writes:

    > Dear all,
    > I did some more tests regarding the == operator in Ops.data.frame (see 
    > below).? All tests done in R 3.6.1 (x86_64-w64-mingw32).

    > I find that errors are thrown also when comparing a zero length 
    > data.frame to atomic objects with length>0 which should be a valid case 
    > according to the documentation. This can be traced to a check in the 
    > last line of Ops.data.frame which tests for the presence of an empty 
    > result value (i.e. list() ) but does not handle a list of empty values 
    > (i.e. list(logical(0))) which in fact is generated in those cases. 

    > There  is a simple fix (see also below).

I'm pretty sure what you write above is wrong:  For some reason
you must have changed more in your own version of Ops.data.frame :

Because there's a line

	value <- unlist(value, ...)

there, value is *not*  list(logical(0)) there, but rather  logical(0)
and then indeed, your proposed line change (at the end of Ops.data.frame)
has no effect for the examples you give.

Note also that your analysis -- treating all 0-extent data
frames or matrices the same -- is very incomplete.

A  0 x 0   matrix is not the same as a   0 x 1  matrix etc,  and
similar for data frames.


Here's an extended "testing" script which takes into account
some of the above :

##-----------------------------------------------------------

d0  <- data.frame(a = numeric(0)) # zero length data.frame
d00 <- unname(d0) # zero length data.frame __without names__
d3   <- data.frame(a=1:3) # non-empty data.frame
d30. <- d3[,FALSE] # 3 x 0 -- take into account, too !
d30  <- unname(d30.)

m01. <- matrix(,0,1, dimnames=list(NULL,"a")) # 0 x 1 matrix with dimnames
m01 <- unname(m01.)
m00. <- matrix(,0,0, dimnames=list(NULL,NULL)) # 0 x 0 matrix with dimnames
m00 <- unname(m00.)
m3 <- data.matrix(d3)
##------------------------
## error A:
## Error in matrix(if (is.null(value)) logical() else value, nrow = nr, dimnames = list(rn,  : 
##   length of 'dimnames' [2] not equal to array extent

d0 == 1   # error A
d00 == 1  # <0 x 0 matrix>
d30. == 1  # <3 x 0 matrix>
d30  == 1  # <3 x 0 matrix>
d3 == 1   # <3 x 1 matrix>

d0 == logical(0) # error A
d00 == logical(0) # <0 x 0 matrix>
d30. == logical()  # <3 x 0 matrix>
d30  == logical()  # <3 x 0 matrix>
d3 == logical(0) # error A

d0 == NULL # error A
d00 == NULL # <0 x 0 matrix>
d30. == NULL  # <3 x 0 matrix>
d30  == NULL  # <3 x 0 matrix>
d3 == NULL # error A

m00 == d0  # error A
m00 == d00 # <0 x 0 matrix>
m00 == d3   # error A


# 0-length matrix for comparison :
identical(m00., m00. == 1) ## 0 x 0 matrix *with* "invisible" dimnames [ NULL, NULL ]
identical(m00., m00. == logical(0))
identical(m00., m00. == NULL)
identical(m00, m00 == 1)   ## 0 x 0 matrix w/o dimnames
identical(m00, m00 == logical(0))
identical(m00, m00 == NULL)
## 0 x 1 ---------------------
identical(m01., m01. == 1)          # < 0 x 1 matrix> *with* dimnames
identical(m01., m01. == logical(0)) #     "             "      "
identical(m01., m01. == NULL)       #     "             "      "
identical(m01, m01 == 1)          # < 0 x 1 matrix> w/o dimnames
identical(m01, m01 == logical(0)) # < 0 x 1 matrix>
identical(m01, m01 == NULL)       # < 0 x 1 matrix>

##-----------------------------------------------------------

Best regards,
Martin



[Rd] '==' operator: inconsistency in data.frame(...) == NULL
Martin Maechler