[As an aside, only part of this is directed at you, Robert; much of it
is meant for the developers, so don't worry if it gets obscure and
technical. I've summarized bits throughout and at the end.]
The manual scales do not have a palette argument. From the
scale_shape_manual page, ... is said to be able to take "common discrete
scale parameters: name, breaks, labels, na.value, limits and guide."
That is an inclusive list, not an example list. In particular, palette
is not a argument that (is meant to be) passed through to a discrete
scale. Now here is where it gets tricky.
By passing a palette, you do override the palette that the manual scale
internally creates from the values argument (which you don't provide).
Because of the argument matching based on named arguments and positional
matching, your passed palette becomes the one used and the internally
determined palette gets kicked to the next argument which happens to be
the name of the guide. (Which explains why when I was debugging, the
error was coming from a text grob.) In particular note:
> dput(scale_shape_manual(palette=p.test))
structure(list(call = discrete_scale(aesthetics = aesthetic,
scale_name = "manual", palette = ..1, name = pal), aesthetics =
"shape",
scale_name = "manual", palette = function (n)
{
21:(20 + n)
}, range = <S4 object of class structure("DiscreteRange", package =
"scales")>,
limits = NULL, na.value = NA, expand = structure(list(), class =
"waiver"),
name = function (n)
{
if (n > length(values)) {
stop("Insufficient values in manual scale. ", n,
" needed but only ", length(values), " provided.",
call. = FALSE)
}
values
}, breaks = structure(list(), class = "waiver"), labels =
structure(list(), class = "waiver"),
legend = NULL, drop = TRUE, guide = "legend"), .Names = c("call",
"aesthetics", "scale_name", "palette", "range", "limits", "na.value",
"expand", "name", "breaks", "labels", "legend", "drop", "guide"
), class = c("manual", "discrete", "scale"))
So, part 1, you should not give a palette argument to a scale_*_manual
function, but ggplot is not doing a good job of protecting its arguments
when you do.
The code you should have used is
plt + scale_shape_discrete(palette=p.test)
... except that doesn't work either do to a similar bug in a different
function. scale_shape_discrete also defines its own palette and passes
that along positionally and thus kicks some other function into the name
which gives the same (effective) error as it tries to write the name of
the legend which is a function instead of a string.
So, part 2, if you do specify it as you are supposed to, it still won't
work because of a bug.
Apparently, despite this palette functionality being there for awhile,
no one has actually attempted to use it before to realize it was broken.
So follow Brandon's advice and specify values instead. At least until
this functionality is working.
--
Brian S. Diggs, PhD
Senior Research Associate, Department of Surgery
Oregon Health & Science University