[Rd] plogis (and other p* functions), vectorized lower.tail
Martin Maechler
m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Thu Dec 9 17:35:33 CET 2021
>>>>> Sokol Serguei on Thu, 9 Dec 2021 17:13:36 +0100 writes:
> On 09/12/2021 16:55, Ben Bolker wrote:
>>
>>
>> On 12/9/21 10:03 AM, Martin Maechler wrote:
>>>>>>>> Matthias Gondan
>>>>>>>> on Wed, 8 Dec 2021 19:37:09 +0100 writes:
>>>
>>> > Dear R developers,
>>> > I have seen that plogis silently ignores vector elements of
>>> lower.tail,
>>>
>>> and also of 'log'.
>>> This is indeed the case for all d*, p*, q* functions.
>>>
>>> Yes, this has been on purpose and therefore documented, in the
>>> case of plogis, e.g. in the 'Value' section of ?plogis :
>>>
>>> The length of the result is determined by ‘n’ for ‘rlogis’, and is
>>> the maximum of the lengths of the numerical arguments for the
>>> other functions.
>>>
>>> (note: *numerical* arguments: the logical ones are not recycled)
>>>
>>> The numerical arguments other than ‘n’ are recycled to the length
>>> of the result. Only the first elements of the logical arguments
>>> are used.
>>>
>>> (above, we even explicitly mention the logical arguments ..)
>>>
>>>
>>> Recycling happens for the first argument (x,p,q) of these
>>> functions and for "parameters" of the distribution, but not for
>>> lower.tail, log.p (or 'log').
>>>
>>>
>>> >> plogis(q=0.5, location=1, lower.tail=TRUE)
>>> > [1] 0.3775407
>>> >> plogis(q=0.5, location=1, lower.tail=FALSE)
>>> > [1] 0.6224593
>>> >> plogis(q=c(0.5, 0.5), location=1, lower.tail=c(TRUE, FALSE))
>>> > [1] 0.3775407 0.3775407
>>>
>>> > For those familiar with psychological measurement: A use case
>>> of the above function is the so-called Rasch model, where the
>>> probability that a person with some specific ability (q) makes a
>>> correct (lower.tail=TRUE) or wrong response (lower.tail=FALSE) to an
>>> item with a specific difficulty (location). A vectorized version of
>>> plogis would enable to determine the likelihood of an entire response
>>> vector in a single call. My current workaround is an intermediate
>>> call to „Vectorize“.
>>>
>>> > I am wondering if the logical argument of lower.tail can be
>>> vectorized (?). I see that this may be a substantial change in many
>>> places (basically, all p and q functions of probability
>>> distributions), but in my understanding, it would not break existing
>>> code which assumes lower.tail to be a single element. If that’s not
>>> > possible/feasible, I suggest to issue a warning if a vector of
>>> length > 1 is given in lower.tail. I am aware that the documentation
>>> clearly states that lower.tail is a single boolean.
>>>
>>> aah ok, here you say you know that the current behavior is documented.
>>>
>>> > Thank you for your consideration.
>>>
>>>
>>> As you mention, changing this would be quite a large endeavor.
>>> I had thought about doing that many years ago, not remembering
>>> details, but seeing that in almost all situations you really
>>> only need one of the two tails (for Gaussian- or t- based confidence
>>> intervals you also only need one, for symmetry reason).
>>>
>>> Allowing the recycling there would make the intermediate C code
>>> (which does the recycling) larger and probably slightly
>>> slower because of conceptually two more for loops which would in
>>> 99.9% only have one case ..
>>>
>>> I'd have found that ugly to add. ... ...
>>> ... but of course, if you can prove that the code bloat would not be
>>> large
>>> and not deteriorate speed in a measurable way and if you'd find
>>> someone to produce a comprehensive and tested patch ...
>>>
>>> Martin
>>>
>>>
>>> > With best wishes,
>>> > Matthias
>>>
>>>
>>>
>>> > [[alternative HTML version deleted]]
>>>
>>> > ______________________________________________
>>> > R-devel using r-project.org mailing list
>>> > https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>> ______________________________________________
>>> R-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>
>>
>> I agree with everything said above, but think that adding a warning
>> when length(lower.tail) > 1 (rather than silently ignoring) might be
>> helpful ... ??
>>
>> As for the vectorization, it seems almost trivial to do at the user
>> level when needed (albeit it's probably a little bit inefficient):
>>
>> pv <- Vectorize(plogis, c("q", "location", "scale", "lower.tail"))
>> pv(q=c(0.5, 0.5), location=1, lower.tail=c(TRUE, FALSE))
>> [1] 0.3775407 0.6224593
> .. or directly use mapply()
> mapply(plogis, q=c(0.5, 0.5), location=1, lower.tail=c(TRUE, FALSE))
> [1] 0.3775407 0.6224593
Very nice, yes. Also, there's no need to recycle/vectorize yourself:
q=0.5 is sufficient:
> mapply(plogis, q=0.5, location=1, lower.tail=c(TRUE, FALSE))
[1] 0.3775407 0.6224593
Martin
More information about the R-devel
mailing list