简体   繁体   中英

Error when plotting in a function with ggplot2

My code to plot a stacked pyramid works well in the terminal window, but it throws an error when inside a function.

Here's my code:

make.pyramid <- function(){
  mydata <- data.frame(factorname=rep(c("first","second"),10), Topic=sort(c(1:10, 1:10)), Distribution=sample(1:200,20))
  mydata <- mydata[order(mydata$factorname,mydata$Topic),]
  topicavg <- c()
  for (row in 1:10) {topicavg[row] <- mydata[row,3]-mydata[row+10,3]}
  topicavg <- c(topicavg,topicavg)
  mydata <- cbind(mydata,topicavg)
  library(ggplot2)
  dist <- ggplot(data=mydata, aes_q(x=substitute(reorder(Topic, topicavg)), y=quote(Distribution), fill=as.name("factorname")))
  dist <- dist + geom_bar(data=subset(mydata,mydata[,1]=="first"), stat="identity")
  dist <- dist + geom_bar(data=subset(mydata,mydata[,1]=="second"), stat="identity", position="identity", mapping=aes(y=-Distribution))
  dist <- dist + scale_y_continuous(labels=abs)
  dist <- dist + xlab("Topics")
  dist <- dist + coord_flip()
  dist <- dist + geom_point(data=subset(mydata,mydata[,1]=="second"), mapping=aes(y=topicavg), shape=4, show.legend = F)
  print(dist)
}

If I step through line by line in the terminal, I get a plot like this: 堆积金字塔图

But when used in the function, I get the following error:

Error in tapply(X = X, INDEX = x, FUN = FUN, ...) : arguments must have same length

Where have I gone wrong, and I how do I make it right?

Yup, another solution is to create seperate functions

makeData <- function() {
  makingData <- data.frame(factorname=rep(c("first","second"),10), Topic=sort(c(1:10, 1:10)), Distribution=sample(1:200,20))
  makingData <- makingData[order(makingData$factorname,makingData$Topic),]
  topicavg <- c()
  for (row in 1:10) {topicavg[row] <- makingData[row,3]-makingData[row+10,3]}
  topicavg <- c(topicavg,topicavg)
  makingData <- cbind(makingData,topicavg)
  return(makingData)
}

make.pyramid <- function(){
  myData <- makeData()
  dist <- ggplot(data=mydata, aes_q(x=substitute(reorder(Topic, topicavg)), y=quote(Distribution), fill=as.name("factorname")))
  dist <- dist + geom_bar(data=subset(mydata,mydata[,1]=="first"), stat="identity")
  dist <- dist + geom_bar(data=subset(mydata,mydata[,1]=="second"), stat="identity", position="identity", mapping=aes(y=-Distribution))
  dist <- dist + scale_y_continuous(labels=abs)
  dist <- dist + xlab("Topics")
  dist <- dist + coord_flip()
  dist <- dist + geom_point(data=subset(mydata,mydata[,1]=="second"), mapping=aes(y=topicavg), shape=4, show.legend = F)
  print(dist)
}

I figured it out! My belief that I was running into problem with ggplot2 threw me off the track. I was actually using the function incorrectly. In this example, I need to define my objects globally even just to use it locally within the function:

make.pyramid <- function(){
  mydata <<- data.frame(factorname=rep(c("first","second"),10), Topic=sort(c(1:10, 1:10)), Distribution=sample(1:200,20))
  mydata <<- mydata[order(mydata$factorname,mydata$Topic),]
  topicavg <<- c()
  for (row in 1:10) {topicavg[row] <- mydata[row,3]-mydata[row+10,3]}
  topicavg <<- c(topicavg,topicavg)
  mydata <<- cbind(mydata,topicavg)
  dist <- ggplot(data=mydata, aes_q(x=substitute(reorder(Topic, topicavg)), y=quote(Distribution), fill=as.name("factorname")))
  dist <- dist + geom_bar(data=subset(mydata,mydata[,1]=="first"), stat="identity")
  dist <- dist + geom_bar(data=subset(mydata,mydata[,1]=="second"), stat="identity", position="identity", mapping=aes(y=-Distribution))
  dist <- dist + scale_y_continuous(labels=abs)
  dist <- dist + xlab("Topics")
  dist <- dist + coord_flip()
  dist <- dist + geom_point(data=subset(mydata,mydata[,1]=="second"), mapping=aes(y=topicavg), shape=4, show.legend = F)
  print(dist)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM