[Rd] ftable <-> data.frame etc {was "justify hard coded in format.ftable"}

Gabor Grothendieck ggrothend|eck @end|ng |rom gm@||@com
Fri May 15 19:58:09 CEST 2020


That's not the problem.  The problem is that if you have

   ft <- ftable(UCBAdmissions, row.vars = 3:2)
   ft
   ##             Admit Admitted Rejected
   ## Dept Gender
   ## A    Male              512      313
   ##      Female             89       19
   ## B    Male              353      207
   ##      Female             17        8
   ## C    Male              120      205
  ## ... etc ...

then as.data.frame(ft) gives a deconstructed 24x4 data.frame
like this:

  as.data.frame(ft)
  ##    Dept Gender    Admit Freq
  ## 1     A   Male Admitted  512
  ## 2     B   Male Admitted  353
  ## 3     C   Male Admitted  120
  ## 4     D   Male Admitted  138
  ## ... etc ...

which is fine but it does not address the problem here.  The
problem here is that we want a a usable data.frame
having columns that correspond to ft.  We want this 12x4
data.frame:

  ##    Dept Gender Admitted Rejected
  ## 1     A   Male      512      313
  ## 2     A Female       89       19
  ## 3     B   Male      353      207
  ## 4     B Female       17        8
  ## ... etc ...

The links I provided already pointed to the code below which
someone posted on SO and solves the problem but I would
have thought this would be easy to do in base R and natural
to provide.

  ftable2df <- function(mydata) {
    ifelse(class(mydata) == "ftable",
        mydata <- mydata, mydata <- ftable(mydata))
    dfrows <- rev(expand.grid(rev(attr(mydata, "row.vars"))))
    dfcols <- as.data.frame.matrix(mydata)
    names(dfcols) <- do.call(
      paste, c(rev(expand.grid(rev(attr(mydata, "col.vars")))), sep = "_"))
    cbind(dfrows, dfcols)
  }
  ftable2df(ft)
  ##    Dept Gender Admitted Rejected
  ## 1     A   Male      512      313
  ## 2     A Female       89       19
  ## 3     B   Male      353      207
  ## 4     B Female       17        8
  ## ... etc ...

 Fri, May 15, 2020 at 12:25 PM Martin Maechler
<maechler using stat.math.ethz.ch> wrote:
>
> >>>>> Gabor Grothendieck
> >>>>>     on Thu, 14 May 2020 06:56:06 -0400 writes:
>
> > If you are looking at ftable could you also consider adding
> > a way to convert an ftable into a usable data.frame such as
> > the ftable2df function defined here:
>
> > https://stackoverflow.com/questions/11141406/reshaping-an-array-to-data-frame/11143126#11143126
>
> > and there is an example of using it here:
>
> > https://stackoverflow.com/questions/61333663/manipulating-an-array-into-a-data-frame-in-base-r/61334756#61334756
>
> > Being able to move back and forth between various base class representations
> > seems like something that would be natural to provide.
>
> Sure!
>
> But there is already an  as.data.frame() method for "ftable",
> {and I would not want the    if(! .. ftable)  ftable(x)  part anyway.
>
> What I think many useRs / programmeRs  very often forget about
> is more-than-2-dimensional arrays {which *are* at the beginning
> of that SO question} and that these are often by far the most
> efficient data structure (rather than the corresponding data frames).
>
> and even less people forget that a "table" in base R is just a
> special case of a 1-D, 2-D, 3-D, .... array.
> (Semantically a special case: "array" with non-negative integer content
>
> I'd claim that everything you here ("move back and forth between
> ...") is already there in the "ftable" implementation in stats,
> notably in the source file  src/library/stats/R/ftable.R
>  -> https://svn.r-project.org/R/trunk/src/library/stats/R/ftable.R
>
> The problem may be in
>
> 1) too sparse documentation about the close relations
>    "ftable" <-> "array" <-> "table" <-> "data.frame"
>
> 2) people not thinking often enough about more-than-2D-arrays and the
>   special corresponding class "table" in R.
>
> To start with one:
>
> > str(UCBAdmissions)
>  'table' num [1:2, 1:2, 1:6] 512 313 89 19 353 207 17 8 120 205 ...
>  - attr(*, "dimnames")=List of 3
>   ..$ Admit : chr [1:2] "Admitted" "Rejected"
>   ..$ Gender: chr [1:2] "Male" "Female"
>   ..$ Dept  : chr [1:6] "A" "B" "C" "D" ...
> >
>
> and look at the *examples* in the help files and the S3 methods
>
> methods(class = "ftable")
> [1] as.data.frame as.matrix     as.table      format        head          print
> [7] tail
> see '?methods' for accessing help and source code
> > methods(class = "table")
>  [1] [             aperm         as.data.frame Axis          coerce        initialize
>  [7] lines         plot          points        print         show          slotsFromS3
> [13] summary       tail
> see '?methods' for accessing help and source code
> >
>
> ... need to close now, there's more to be said ...
>
>
>
>     > On Thu, May 14, 2020 at 5:32 AM Martin Maechler
>     > <maechler using stat.math.ethz.ch> wrote:
>     >>
>     >> >>>>> SOEIRO Thomas
>     >> >>>>>     on Wed, 13 May 2020 20:27:15 +0000 writes:
>     >>
>     >> > Dear all,
>     >> > I haven't received any feedback so far on my proposal to make "justify" argument available in stats:::format.ftable
>     >>
>     >> > Is this list the appropriate place for this kind of proposal?
>     >>
>     >> Yes, it is.. Actually such a post is even a "role model" post
>     >> for R-devel.
>     >>
>     >> > I hope this follow-up to my message won't be taken as rude. Of course it's not meant to be, but I'm not used to the R mailing lists...
>     >>
>     >> well, there could be said much, and many stories told here ... ;-)
>     >>
>     >> > Thank you in advance for your comments,
>     >>
>     >> > Best,
>     >> > Thomas
>     >>
>     >> The main reasons for "no reaction" (for such nice post) probably
>     >> are combination of the following
>     >>
>     >> - we are busy
>     >> - if we have time, we think other things are more exciting
>     >> - we have not used ftable much/at all and are not interested.
>     >>
>     >> Even though the first 2 apply to me, I'll have a 2nd look into
>     >> your post now, and may end up well agreeing with your proposal.
>     >>
>     >> Martin Maechler
>     >> ETH Zurich  and  R Core team
>     >>
>     >>
>     >>
>     >>
>     >> >> Dear all,
>     >> >>
>     >> >> justify argument is hard coded in format.ftable:
>     >> >>
>     >> >> cbind(apply(LABS, 2L, format, justify = "left"),
>     >> >> apply(DATA, 2L, format, justify = "right"))
>     >> >>
>     >> >> It would be useful to have the possibility to modify the argument between c("left", "right", "centre", "none") as in format.default.
>     >> >>
>     >> >> The lines could be changed to:
>     >> >>
>     >> >> if(length(justify) != 2)
>     >> >> stop("justify must be length 2")
>     >> >> cbind(apply(LABS, 2L, format, justify = justify[1]),
>     >> >> apply(DATA, 2L, format, justify = justify[2]))
>     >> >>
>     >> >> The argument justify could defaults to c("left", "right") for backward compatibility.
>     >> >>
>     >> >> It could then allow:
>     >> >> ftab <- ftable(wool + tension ~ breaks, warpbreaks)
>     >> >> format.ftable(ftab, justify = c("none", "none"))
>     >> >>
>     >> >> Best regards,
>     >> >>
>     >> >> Thomas
>
>
>     > --
>     > Statistics & Software Consulting
>     > GKX Group, GKX Associates Inc.
>     > tel: 1-877-GKX-GROUP
>     > email: ggrothendieck at gmail.com



-- 
Statistics & Software Consulting
GKX Group, GKX Associates Inc.
tel: 1-877-GKX-GROUP
email: ggrothendieck at gmail.com



More information about the R-devel mailing list