Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong error message with NA name in scale_linetype_manual, inconsistent with scale_color_manual #2206

Closed
jsams opened this issue Jul 14, 2017 · 4 comments
Labels
bug an unexpected problem or unintended behavior scales 🐍

Comments

@jsams
Copy link

jsams commented Jul 14, 2017

When NAs are included as a name with the scale_linetype_manual, an incorrect error occurs:

Error in grid.Call.graphics(C_lines, x$x, x$y, index, x$arrow) :
  invalid hex digit in 'color' or 'lty'

The error says that the linetype or color given is invalid even when all colors and linetypes are in fact valid. The problem is with an NA in the names of the value vector given to the scale_linetype_manual function.

However, the same vector of names with colors (with color identifiers rather than linetype identifiers) does not produce an error (although the line does not get drawn either).

It seems as if an NA value is given a specific linetype, then the line should be drawn. Even if you disagree, the error message given should point the user at the correct problem, an NA in the names, and not send them down a rabbit hole trying to diagnose a non-problem.

Here is some code that demonstrates both the inconsistent behavior and the error

library(ggplot2)
library(data.table)
library(RColorBrewer)


# Setup
line_types = c('solid', 'dotted', 'longdash')
color_group = 'Paired' # 'Dark2'...
IS_POOL = c(NA_character_, letters) # pool of names to label lines
IPTS = 6 # how many lines to plot
IS = IS_POOL[1:IPTS]
DENPTS = 20 # the number of points used to draw the density
BUG_FIX = F

if (BUG_FIX) {
    IS[is.na(IS)] = "NA"
}

dt = data.table(index=rep(1:IPTS, each=DENPTS),
                 x=rep(seq(-4,4, length.out=DENPTS), times=IPTS))
dt[, i := IS[index]]
setkey(dt, i, x)
dt[, `:=`(mean=rnorm(1), var=runif(1, 0.5, 2)), by=.(i)]
dt[, density := dnorm(x, mean, var)]


# set up line and color sequences
colors = brewer.pal(ceiling(length(IS) / length(line_types)), color_group)
colorrep = rep(colors, each=length(line_types))[1:length(IS)]
names(colorrep) = IS
linerep = rep(line_types, times=length(colors))[1:length(IS)]
names(linerep) = IS

# this works fine
plt = ggplot(dt) + geom_line(aes(x=x, y=density, color=i, linetype=i))
plt

#  this works fine, despite the NA in colorrep
plt = plt + scale_color_manual(values=colorrep)
plt

# this fails with, even though linerep and colorrep names are setup identically
# Error in grid.Call.graphics(C_lines, x$x, x$y, index, x$arrow) :
#   invalid hex digit in 'color' or 'lty'
plt + scale_linetype_manual(values=linerep)
@karawoo
Copy link
Member

karawoo commented Jul 14, 2017

It does seem like linetype should behave the same as colour here. Below is a more minimal example. In the future it's helpful if you can make your example as minimal as possible to isolate the problem.

library("scales")
library("ggplot2")

## Classes in the data
lvls <- levels(economics_long$variable)

## Vectors of colors and linetypes
colors <- viridis_pal()(length(lvls))
types <- c("solid", "dashed", "dotted", "dotdash", "longdash")

## Add one too few names
names(colors) <- lvls[-1]
names(types) <- lvls[-1]

colors
#>         pop     psavert     uempmed    unemploy        <NA> 
#> "#440154FF" "#3B528BFF" "#21908CFF" "#5DC863FF" "#FDE725FF"
types
#>        pop    psavert    uempmed   unemploy       <NA> 
#>    "solid"   "dashed"   "dotted"  "dotdash" "longdash"

ggplot(economics_long, aes(date, value01, colour = variable)) +
  geom_line() +
  scale_colour_manual(values = colors)

ggplot(economics_long, aes(date, value01, linetype = variable)) +
  geom_line() +
  scale_linetype_manual(values = types)
#> Error in grid.Call.graphics(C_lines, x$x, x$y, index, x$arrow): invalid hex digit in 'color' or 'lty'

@karawoo karawoo added bug an unexpected problem or unintended behavior scales 🐍 labels Jul 14, 2017
@hadley
Copy link
Member

hadley commented Oct 30, 2017

Even more minimal reprex:

df <- data.frame(x = 1:2, y = 1:2, z = "a")
ggplot(df, aes(x, y)) + 
  geom_line(aes(linetype = z)) + 
  scale_linetype_manual(values = NA)

@hadley
Copy link
Member

hadley commented Oct 30, 2017

I think the root cause of this is a bug in keep() inside GeomPath$handle_na() - it's failing to drop NA if all entries within a group are missing.

@hadley
Copy link
Member

hadley commented Oct 30, 2017

Still more minimal reprex:

df <- data.frame(x = 1:2, y = 1:2, z = "a")
ggplot(df, aes(x, y)) + geom_line(linetype = NA)

@hadley hadley closed this as completed in 884fdcb Oct 30, 2017
@lock lock bot locked as resolved and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug an unexpected problem or unintended behavior scales 🐍
Projects
None yet
Development

No branches or pull requests

3 participants