Data created from empty data.table causes ggplot error ("replacement has 1 row, data has 0")

Viewed 175

I'm trying to plot two continuous variables generated from a linear model with ggplot but I have a strange error that pops-up.

Here is a reproducible example:

library(data.table)
library(ggplot2)
set.seed(1)

n <- 4

DT <- data.table()
DT[, x := rnorm(n)]
DT[, z := rep(-.5:+.5, each = n/2)]
DT[, e := rnorm(n, 0.5)]
DT[, y := 1 + 2*x + 3*z + 4*x*z + e]

ggplot(DT, aes(x, y)) + geom_point()

When executed, the scripts returns the following error:

> ggplot(DT, aes(x, y)) + geom_point()
Error in `$<-.data.frame`(x, name, value) : 
  replacement has 1 row, data has 0

There doesn't seems to be any issue with the generated data:

> DT
            x    z          e          y
1: -0.6264538 -0.5  0.8295078  0.3295078
2:  0.1836433 -0.5 -0.3204684 -0.8204684
3: -0.8356286  0.5  0.9874291  0.1449146
4:  1.5952808  0.5  1.2383247 10.1194479

> str(DT)
Classes ‘data.table’ and 'data.frame':  4 obs. of  4 variables:
 $ x: num  -0.626 0.184 -0.836 1.595
 $ z: num  -0.5 -0.5 0.5 0.5
 $ e: num  0.83 -0.32 0.987 1.238
 $ y: num  0.33 -0.82 0.145 10.119
 - attr(*, ".internal.selfref")=<externalptr> 

Curiously, the following code works without issues:

DT2 <- data.table(x = rnorm(n), y = rnorm(n))
ggplot(DT2, aes(x, y)) + geom_point()

I'm not sure what the issue is, but my guess is that ggplot doesn't like how my data is being generated.

1 Answers

This is an open issue as of data.table 1.12.8 : data.table not compatible with ggplot when it was generated from empty data.table.

The reason appears to be that the data created from an empty data.table "does not get row names after assignment."

rownames(DT)
# character(0)

"We can manually work around this by setting the [row names] attribute":

setattr(DT, "row.names", seq.int(n))
rownames(DT) 
# [1] "1" "2" "3" "4"

ggplot(DT, aes(x, y)) + geom_point()
# works!

Another work around suggested by the OP in the issue, is to convert to data.frame (setDF) (and then possibly also convert it back to data.table).

Related