1

After defining this function:

compare <- function(list.a, list.b, selection)
{
  dev.new()
  df <- melt(as.data.frame(t(matrix(c( list.a[selection], list.b[selection]), nrow=2, byrow=TRUE))))
  xaxis <- rep(c(1:length(selection)), 2)
  ggplot(df, aes(x=xaxis, y=value, group=variable)) + geom_line()
}

[EDIT]

I just realized this code needs two requires to run:

require(ggplot2)
require(reshape)

And it can be summarized into a single line problem like this:

compare <- function(list.a, list.b, selection) ggplot() + geom_line(data=melt(as.data.frame(t(matrix(c( list.a[selection], list.b[selection]), nrow=2, byrow=TRUE)))), aes_string(x=rep(1:length(selection), 2), y="value", colour="variable"))

The expected output of this function is a linechart of two lists of values (a and b), but only plotting a certain range (selection) from those two lists; see an example function call below.

The one-line version of the function, by the way, does work, but the output is wrong: it produces a single line instead of the desired linechart. But if I unquote the value and variable variables (generated by the melt() call - that is melt.data.frame(), actually), then I get the same error as below ("object not found"), but now it does not find value: object 'value' not found.

Here is the "default", clean version of the function; same problem, though:

compare <- function(list.a, list.b, selection)
{
  df <- melt(as.data.frame(t(matrix(c( list.a[selection], list.b[selection]), nrow=2, byrow=TRUE))))
  xaxis <- rep(c(1:length(selection)), 2)
  ggplot(df, aes(x=xaxis, y=value, colour=variable)) + geom_line()
}

Calling any version of these functions with:

compare(runif(100), runif(100), 30:80)

Should have produced a linechart of two lines with random values in the [0,1] range on the y-axis, over 51 values taken from index 30 to 80 in both lists.

[/EDIT]

But I get the following error:

Error in eval(expr, envir, enclos) : object 'xaxis' not found

I have no clue why I am getting this error or how to prevent it. Anybody can solve this for me, please, and tell me what I am doing wrong?

fnl
  • 4,861
  • 4
  • 27
  • 32
  • Right off the bat I can tell you that xaxis is not a part of the data frame df and I'm sure that's directly related to your issue (i.e. 'xaxis' not found). If you can provide a small reproducible example I'm sure we can provide some more insight – Steve Reno Apr 29 '14 at 15:12
  • Found the reason: ggplot2 is made for the global environment! compare <- function(list.a, list.b, selection) { df <- melt(as.data.frame(t(matrix(c( list.a[selection], list.b[selection]), nrow=2, byrow=TRUE)))); xaxis <- rep(c(1:length(selection)), 2); ggplot(df, aes_string(x="xaxis", y="value", colour="variable")) + geom_line() } Note the change from `aes()` to `aes_string()` and using strings instead of references. Here is Hadley's own explanation for the problem: http://tolstoy.newcastle.edu.au/R/e3/help/07/12/6372.html – fnl Apr 29 '14 at 15:16
  • OK, after checking again, the change commented above (using `aes_string()`) worked because I had an xaxis defined in the global env... So the question is still not answered, and I actually get the same error even when using `aes_string()`. I also tried adding an `e <- environment(); ggplot(..., aes_string(..., environment=e))` to the mix, but that did not help, either. @SteveReno: the code above is a small reproducible example, actually. Let me know if you have problems. – fnl Apr 29 '14 at 15:42
  • 1
    @SteveReno I think I have found your problem: you need to `require(ggplot2)` and `require(reshape)` to run my code. – fnl Apr 29 '14 at 15:58

3 Answers3

2

I had the same problem and found the answer here: Use of ggplot() within another function in R

As suggested there, adding environment parameter like below worked for me:

library(reshape2)
library(ggplot2)

compare <- function(list.a, list.b, selection)
{
  df <- melt(as.data.frame(t(matrix(c( list.a[selection], list.b[selection]), nrow=2, byrow=TRUE))))
  xaxis <- rep(c(1:length(selection)), 2)
  # ggplot(df, aes(x=xaxis, y=value, colour=variable)) + geom_line() # fails
  ggplot(df, aes(x=xaxis, y=value, colour=variable),environment=environment()) + geom_line() # works
}

compare(runif(100, 0, 1), runif(100, 0, 1), c(30:80))
Community
  • 1
  • 1
ckcn
  • 179
  • 1
  • 9
  • Thanks, @ckcn. Yes, the question/answer you link to nicely explains what is going on here and how to avoid the problem. – fnl May 04 '16 at 08:14
1

As per my previous comment, including 'xaxis' in your df dataframe seems to correct this error.

This code works for me

library(reshape2)
library(ggplot2)

compare <- function(list.a, list.b, selection)
  {
  dev.new()
  df <- melt(as.data.frame(t(matrix(c( list.a[selection], list.b[selection]), nrow=2,    byrow=TRUE))))
  df$xaxis <- rep(c(1:length(selection)), 2)
  ggplot(df, aes(x=xaxis, y=value, group=variable)) + geom_line()
}

compare(runif(100, 0, 1), runif(100, 0, 1), c(30:80))
Steve Reno
  • 1,304
  • 3
  • 14
  • 21
  • OK, you were a few seconds faster than @infominer (sorry, infominer!); Just, could you please explain why this actually happens? Does this mean ggplot aesthetics only can reference variables defined in the plotted data's dataframe or so? – fnl Apr 29 '14 at 16:16
  • It appears that within your function call 'xaxis' originally was not within the scope of ggplot. I'm actually unsure why this happens, if you explicitly set the values list.a, list.b, and selection and then just run your original code inside the function it does not appear to have an issue, but within the function call it apparently does not know about 'xaxis'. I always put everything I want to use in a ggplot in the data= data frame, and I've never had an issue. – Steve Reno Apr 29 '14 at 16:24
  • 1
    if you put something within the function call, scope is limited to within the function, unless you explicity pass it parameters that are globally defined – infominer Apr 29 '14 at 16:28
  • Thanks, both. So here is the final, cleaned up working version of my function: `compare <- function(list.a, list.b, selection) { lists <- melt(data.frame(a=list.a[selection], b=list.b[selection])) lists$abscissa <- rep(c(1:length(selection)), 2); ggplot(lists, aes(x=abscissa, y=value, colour=variable)) + geom_line() }` – fnl Apr 30 '14 at 08:40
1

Change your function to this

compare <- function(list.a, list.b, selection) {
df <- melt(as.data.frame(
                          t(matrix(c(list.a[selection], list.b[selection]), 
                                  nrow = 2, byrow = TRUE))))
print(head(df)) #before adding axis to your df
df$xaxis <- rep(c(1:length(selection)), 2)
print(head(df)) #after adding the axis to your df
ggplot(df, aes(x=xaxis, y=value, colour=variable)) + geom_line()

}

the print statements can be removed, they are there to show you what ggplot sees. You can also use aes_string, but you still need to make a new data.frame with all the "columns" you're passing to ggplot

infominer
  • 1,981
  • 13
  • 17