Ben Bolker
Ben Bolker

Reputation: 226097

tidyverse analog of reshape2::melt that does everything?

The answers to this question document that the tidyverse analog of reshape2::melt() is tidyr::pivot_longer(). That's true, as far as it goes, but I still find the process of melting a matrix with defined dimnames in tidyverse much less convenient than the tidyverse equivalent.

Example:

z <- matrix(1:12, ncol=3, 
       dimnames = list(a = 1:4, b = LETTERS[1:3]))

reshape2::melt(z) automatically gives me a data frame with the ID columns named "a" and "b", corresponding to the elements of names(dimnames(z)).

I originally had a somewhat clunky solution here but realized it didn't work. I think the required steps are

This seems much clunkier than melt(). Obviously I could write a utility function to encapsulate this, but I'm wondering if I'm missing a solution that is more compact and/or tidyverse-idiomatic. What do other people do when the first step in their data pipeline is a matrix?

Upvotes: 5

Views: 254

Answers (1)

Allan Cameron
Allan Cameron

Reputation: 173793

If you don't mind having a base R function in your pipeline, then you could do:

z %>%
  as.table() %>%
  as_tibble()
#> # A tibble: 12 x 3
#>    a     b         n
#>    <chr> <chr> <int>
#>  1 1     A         1
#>  2 2     A         2
#>  3 3     A         3
#>  4 4     A         4
#>  5 1     B         5
#>  6 2     B         6
#>  7 3     B         7
#>  8 4     B         8
#>  9 1     C         9
#> 10 2     C        10
#> 11 3     C        11
#> 12 4     C        12

Of course, this is just a slightly contrived tidyverse version of the base R equivalent, which is difficult to beat for brevity.

as.data.frame(as.table(z))
#>    a b Freq
#> 1  1 A    1
#> 2  2 A    2
#> 3  3 A    3
#> 4  4 A    4
#> 5  1 B    5
#> 6  2 B    6
#> 7  3 B    7
#> 8  4 B    8
#> 9  1 C    9
#> 10 2 C   10
#> 11 3 C   11
#> 12 4 C   12

And these both give the same result as reshape2::melt:

reshape2::melt(z)
#>    a b value
#> 1  1 A     1
#> 2  2 A     2
#> 3  3 A     3
#> 4  4 A     4
#> 5  1 B     5
#> 6  2 B     6
#> 7  3 B     7
#> 8  4 B     8
#> 9  1 C     9
#> 10 2 C    10
#> 11 3 C    11
#> 12 4 C    12

Created on 2023-01-24 with reprex v2.0.2

Upvotes: 4

Related Questions