38

I would like to make a plot with X values as a subset of the measurement and Y-values as another subset of the measured data.

In the example as below, I have 4 products p1, p2, p3 and p4. Each are priced according to their skew, color and version. I would like to create a multi-facet plot that depicts the P3 products (Y-axis) vs P1 products (X-axis).

My attempt as below has failed miserably with the following error:

Error: Aesthetics must either be length one, or the same length as the dataProblems:subset(price, product == "p1"), subset(price, product == "p3")

library(ggplot2)
product=c("p1","p1","p1","p1","p1","p1","p1","p1","p2","p2","p2","p2","p2","p2","p2","p2","p3","p3","p3","p3","p3","p3","p3","p3","p4","p4","p4","p4","p4","p4","p4","p4")
skew=c("b","b","b","b","a","a","a","a","b","b","b","b","a","a","a","a","b","b","b","b","a","a","a","a","b","b","b","b","a","a","a","a")
version=c(0.1,0.1,0.2,0.2,0.1,0.1,0.2,0.2,0.1,0.1,0.2,0.2,0.1,0.1,0.2,0.2,0.1,0.1,0.2,0.2,0.1,0.1,0.2,0.2,0.1,0.1,0.2,0.2,0.1,0.1,0.2,0.2)
color=c("C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2","C1","C2")
price=c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32)
df = data.frame(product, skew, version, color, price)
# First plot all the data
p1 <- ggplot(df, aes(x=price, y=price, colour=factor(skew))) + geom_point(size=2, shape=19)
p1 <- p1 + facet_grid(version ~ color)
p1 # This gavea very good plot. So far so good
# Now plot P3 vs P1
p1 <- ggplot(df, aes(x=subset(price, product=='p1'), y=subset(price, product=='p3'), colour=factor(skew))) + geom_point(size=2, shape=19)
p1
# failed with: Error: Aesthetics must either be length one, or the same length as the dataProblems:subset(price, product == "p1"), subset(price, product == "p3")

This is the result I am expecting:

This is the result I am expecting

zx8754
  • 52,746
  • 12
  • 114
  • 209
Riad
  • 953
  • 3
  • 13
  • 23

5 Answers5

24

It is better to not subset the variables inside aes(), and instead transform your data:

df1 <- unstack(df,form = price~product)
df1$skew <- rep(letters[2:1],each = 4)

p1 <- ggplot(df1, aes(x=p1, y=p3, colour=factor(skew))) + 
        geom_point(size=2, shape=19)
p1
joran
  • 169,992
  • 32
  • 429
  • 468
22

The problem is that skew isn't being subsetted in colour=factor(skew), so it's the wrong length. Since subset(skew, product == 'p1') is the same as subset(skew, product == 'p3'), in this case it doesn't matter which subset is used. So you can solve your problem with:

p1 <- ggplot(df, aes(x=subset(price, product=='p1'),
                     y=subset(price, product=='p3'),
                     colour=factor(subset(skew, product == 'p1')))) +
              geom_point(size=2, shape=19)

Note that most R users would write this as the more concise:

p1 <- ggplot(df, aes(x=price[product=='p1'],
                     y=price[product=='p3'],
                     colour=factor(skew[product == 'p1']))) +
              geom_point(size=2, shape=19)
David Robinson
  • 77,383
  • 16
  • 167
  • 187
  • Hi @DavidRobinson, your solution worked very fine, I have tried the second one as suggested. The issue is that when I add a facet_grid(version ~ color), I get all my data points replicated in the 4 facets. Any idea ? – Riad Nov 18 '13 at 23:09
6

Similar to @joran's answer. Reshape the df so that the prices for each product are in different columns:

xx <- reshape(df, idvar=c("skew","version","color"),
              v.names="price", timevar="product", direction="wide")

xx will have columns price.p1, ... price.p4, so:

ggp <- ggplot(xx,aes(x=price.p1, y=price.p3, color=factor(skew))) +
       geom_point(shape=19, size=5)
ggp + facet_grid(color~version)

gives the result from your image.

jlhoward
  • 58,004
  • 7
  • 97
  • 140
1

I hit this error because I was specifying a label attribute in my geom (geom_text) but was specifying a color in the top level aes:

df <- read.table('match-stats.tsv', sep='\t')
library(ggplot2)

# don't do this!
ggplot(df, aes(x=V6, y=V1, color=V1)) +
  geom_text(angle=45, label=df$V1, size=2)

To fix this, I just moved the label attribute out of the geom and into the top level aes:

df <- read.table('match-stats.tsv', sep='\t')
library(ggplot2)

# do this!
ggplot(df, aes(x=V6, y=V1, color=V1, label=V1)) +
  geom_text(angle=45, size=2)
duhaime
  • 25,611
  • 17
  • 169
  • 224
0

I encountered this problem because the dataset was filtered wrongly and the resultant data frame was empty. Even the following caused the error to show:

ggplot(df, aes(x="", y = y, fill=grp))

because df was empty.

Rafs
  • 614
  • 8
  • 19