matttproud.com (blog)

A Rant on R and the Melt Function in R

Zürich, Schweiz

I need to be honest: I find the documentation for R frustrating, particularly the API documentation. From the perspective of a professional software engineer, much of the API documentation is unhelpful. There are several common problems:

Note: You could make an argument that static typing would help with this, and you’d be right. The problem is that is not R.

The only thing that seems consistent about is its inconsistency. I’m not alone in feeling that, as there’s a long history of loathing of the R Language:

But, anyway, here we are, and here I am. I have a motivating example of frustration from my day-to-day experience.

There’s a function from reshape2 that gets my ire: melt. It’s been something I’ve used a lot lately. I try not to be a copy-and-paste programmer, but sometimes I need to rely on the structure of existing solutions and documentation, and melt has been a staple of these documents due to the structure of the data I have been working with. Let’s see what the documentation about melt says:

This the generic melt function. See the following functions for the details about different data structures:

How on Earth am I supposed to make sense of what that means? It makes aa little more sense when contextualized with what I read from reshape2’s documentation:

Title Flexibly Reshape Data: A Reboot of the Reshape Package … Description Flexibly restructure and aggregate data using just two functions: melt and ‘dcast’ (or ‘acast’).

So melt in some way restructures the data? Great. But how, and what kind of restructuring should I anticipate?

Well, let’s try to improve our understanding of what this function does visually.

Let’s suppose we have a data frame that has two columns named after siloed but mutually-compatible data streams that can be aggregated together (like temperature observations):

1
df.temps <- data.frame(twin_cities=c(-5, 0, 1), zuerich=c(3, 6, 4))

The data looks like this:

twin_citieszuerich
-53
06
14

Let’s suppose we want to restructure df.temps into something where we identify locality by the value of the column, not the column’s name. This is where melt comes in:

1
2
3
library(reshape2)

df.melted <- melt(df.temps)

The melted data looks like this:

variablevalue
twin_cities-5
twin_cities0
twin_cities1
zuerich3
zuerich6
zuerich4

Note: The column names twin_cities and zuerich are transposed into the new column variable and the respective values for those columns are seen now in value.

You might wonder why this somewhat denormalized form could be preferable? It works great with ggplot2 to lowercase-f facet the data:

1
2
3
4
library(ggplot2)

ggplot(df.melted, aes(x=variable, y=value, color=variable)) +
  geom_boxplot()
Simple Whisker Plot

Now let’s adapt that original data frame to add a column that identifies the row like a timestamp (ts), because this becomes interesting.

1
2
3
4
df.temps <- data.frame(
  ts=c('2024-03-03', '2024-03-04', '2024-03-05'),
  twin_cities=c(-5, 0, 1),
  zuerich=c(3, 6, 4))

It looks similar to the original:

tstwin_citieszuerich
2024-03-03-53
2024-03-0406
2024-03-0514

We can melt that data, and suddenly it is indexable with ts as follows:

1
df.melted <- melt(df.temps, id.vars = c('ts'))

Which is tabularly:

tsvariablevalue
2024-03-03twin_cities-5
2024-03-04twin_cities0
2024-03-05twin_cities1
2024-03-03zuerich3
2024-03-04zuerich6
2024-03-05zuerich4

And now a nice time series can be produced:

1
2
 ggplot(df.melted, aes(x=ts, y=value, color=variable)) +
  geom_point()
Simple Time Series

But back to the question at-hand: documentation quality in R. Python Pandas has an analogue for melt with pandas.melt. Let’s compare the documentation:

Unpivot a DataFrame from wide to long format, optionally leaving identifiers set.

This function is useful to massage a DataFrame into a format where one or more columns are identifier variables (id_vars), while all other columns, considered measured variables (value_vars), are “unpivoted” to the row axis, leaving just two non-identifier columns, ‘variable’ and ‘value’.

That documentation fragment isn’t perfect, but it’s infinitely better than reshape2’s. So a call of action to the R community: please improve the documentation and accessibility of high-touch APIs.

Navigation:
Tags: