问题
I am trying to make a plot using barchart from lattice, but I am having some issues with unused factors for a given panel. I have tried using drop.unused.levels
but it seems it only drops factors when they are not used in any panel.
This is the data frame that I am using:
dm <- structure(list(Benchmark = structure(c(1L, 2L, 3L, 4L, 5L, 6L,
7L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 1L,
2L, 3L, 4L, 5L, 6L, 7L, 1L, 2L, 3L, 4L, 5L, 6L, 7L), class = "factor", .Label = c("416.gamess",
"429.mcf", "436.cactusADM", "458.sjeng", "462.libquantum", "471.omnetpp",
"482.sphinx3")), Class = structure(c(3L, 1L, 2L, 3L, 1L, 4L,
2L, 3L, 1L, 2L, 3L, 1L, 4L, 2L, 3L, 1L, 2L, 3L, 1L, 4L, 2L, 3L,
1L, 2L, 3L, 1L, 4L, 2L, 3L, 1L, 2L, 3L, 1L, 4L, 2L), class = "factor", .Label = c("CS",
"PF", "PI", "PU")), Config = structure(c(1L, 1L, 1L, 1L, 1L,
1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,
4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L), .Label = c("Disabled",
"Shallowest", "Deepest", "StorePref", "StridedPref"), class = "factor"),
Perf = c(1, 0.72, 0.8, 1, 0.32, 1.16, 0.79, 1, 0.98, 1, 1,
0.72, 1, 0.99, 1, 0.98, 1, 1, 1.12, 0.97, 1, 1, 0.97, 1,
1, 0.99, 0.97, 1, 1, 1.18, 1, 1, 0.99, 0.97, 1)), .Names = c("Benchmark",
"Class", "Config", "Perf"), row.names = c(NA, -35L), class = "data.frame")
First I attempted using barchart
like this:
barchart(Perf ~ Benchmark | Class, dm, groups=Config,
scales=list(x=list(relation='free')), auto.key=list(columns=3))
That gave me the following plot:

As you can see, there is a gap between the benchmarks for PI, PF and CS classes. The reason is that each factor is only present in a given class, thus it is missing in all the others, and barchart
might introduce a gap in the x axis.
My second attempt was to call barchart
four times (one for each class):
class.subset <- function(dframe, class.name) {
return(dframe[dframe$Class == class.name, ])
}
pl1 <- barchart(Perf ~ Benchmark, class.subset(dm, 'PI'), groups=Config)
pl2 <- barchart(Perf ~ Benchmark, class.subset(dm, 'PF'),, groups=Config)
pl3 <- barchart(Perf ~ Benchmark, class.subset(dm, 'CS'),, groups=Config)
pl4 <- barchart(Perf ~ Benchmark, class.subset(dm, 'PU'),, groups=Config)
print(pl1, split=c(1, 1, 2, 2), more = TRUE)
print(pl2, split=c(1, 2, 2, 2), more = TRUE)
print(pl3, split=c(2, 1, 2, 2), more = TRUE)
print(pl4, split=c(2, 2, 2, 2))
The plot that I got is pretty much what I want, but now I do not know how to create a single global legend for all the subplots (instead of the very same legend for each subplot):

Ideally, I would prefer to solve the problem that I am facing using the first approach (since in that way I would also have the class name in each of the panels). However, if in the second case, it is possible to add a global legend and a title for each subplot containing the class name, that would be okay too.
回答1:
Here's a quick way using latticeExtra
:
pl1 <- barchart(Perf ~ Benchmark|Class, class.subset(dm, 'PI'), groups=Config,
auto.key=list(columns=3))
pl2 <- barchart(Perf ~ Benchmark|Class, class.subset(dm, 'PF'), groups=Config)
pl3 <- barchart(Perf ~ Benchmark|Class, class.subset(dm, 'CS'), groups=Config)
pl4 <- barchart(Perf ~ Benchmark|Class, class.subset(dm, 'PU'), groups=Config)
library(latticeExtra)
pls <- c(pl1, pl2, pl3, pl4)
pls <- update(pls, scales=list(y="same"))
pls

回答2:
I was just having the same problem in a factor with 95 levels and for lattice::xyplot
.
What worked for me is (with factor being the variable with too many levels):
library(gdata)
key<-simpleKey(levels(drop.levels(df$factor)),...)
xyplot(response~predictor,groups=factor, data=df, key=key)
Worked like a charm for me. Best wishes!
来源:https://stackoverflow.com/questions/12391429/removing-per-panel-unused-factors-in-a-bar-chart