xq1515426 xq1515426 - 1 month ago 9
R Question

"Object '...' not found when referenced object is a nested function in R

Trying to nest functions with in a function to return a list in R after taking in a data frame. But running into a problem right away getting the error:


Error in ------frqTbl <- function(df) { : object 'frqTbl' not found


Is there some way to define a variable that's a function before the function definition? Or is the nesting incorrect?

Tested with:

data(diamonds, package = "ggplot2")
test <- diamonds[1:100,]
mstrFnct(test)

mstrFnct <- function(df){
output <- list()
frqTbl <- function(df){
fctvr <- df[sapply(df,is.factor)]
logicvr <- df[sapply(df,is.logical)]
nwDf <- data.frame(fctvr,logicvr)
if(ncol(nwDf)>0){
freq <-list()
for (i in 1:ncol(nwDf)){
freq[[i]] <- as.data.frame(table((nwDf)[,i]))
names(freq[[i]])[1]=colnames(nwDf[i])
}
return(freq)
}
else{
print("There are no categorical or logical variables in the data
frame.")
}
}
output[[length(output)+1]] <- frqTbl(df)
rSqd <- function(df){
y <- df[sapply(df,is.numeric)]
if(ncol(y)>=2){
c <- combn(colnames(y), 2)
vrPrs <- paste(c[1,], c[2,], sep = "-")
m <- cor(y, method = "pearson")
r <- m[which(lower.tri(m))]
vlus <- r^2
df2 <- data.frame(vrPrs, values)
names(df2) <- sub("^VrPrs$", "Variable Pairs",
names(df2))
names(df2) <- sub("^vlus$", "R-Square", names(df2))
format.data.frame(df2)
return(df2)
}
else{
print(paste("This Data Frame does not have two or more numerical
columns to compute the Pearson correlation coefficient(s)."))
}
}
output[[length(output)+1]] <- rSqd(df)
}

Answer

Is there some way to define a variable that's a function before the function definition?

No. (see first code chunk)

Or is the nesting incorrect?

Actually not. You just messed up the variable names. (see second code chunk)

I suggest the following code to cover your example:

frqTbl <- function(df){

  fctvr <- df[sapply(df,is.factor)]
  logicvr <- df[sapply(df,is.logical)] 
  nwDf <- data.frame(fctvr,logicvr)

  if(ncol(nwDf)>0){ 

    freq <-list() 
    for (i in 1:ncol(nwDf)){ 

      freq[[i]] <- as.data.frame(table((nwDf)[,i]))
      names(freq[[i]])[1]=colnames(nwDf[i])
    } 
    return(freq)
  }
  else{
    print("There are no categorical or logical variables in the data   
            frame.")  
  }
}

rSqd <- function(df){

  y <- df[sapply(df,is.numeric)] 

  if(ncol(y)>=2){ 

    c <- combn(colnames(y), 2) 

    vrPrs <- paste(c[1,], c[2,], sep = "-")

    m <- cor(y, method = "pearson")

    r <- m[which(lower.tri(m))] 

    vlus <- r^2

    df2 <- data.frame(vrPrs, vlus)

    names(df2) <- sub("^vrPrs$", "Variable Pairs", 
                      names(df2)) 
    names(df2) <- sub("^vlus$", "R-Square", names(df2))


    format.data.frame(df2) 
    return(df2)

  }
  else{
    print(paste("This Data Frame does not have two or more numerical  
            columns to compute the Pearson correlation coefficient(s)."))
  }
}

mstrFnct <- function(df){

  output <- list()
  output[[length(output)+1]] <- frqTbl(df)
  output[[length(output)+1]] <- rSqd(df)

  return(output)
}

data(diamonds, package = "ggplot2")
test <- diamonds[1:100,]
mstrFnct(test)

But you could also pack the function definitions into the master function. Like this:

mstrFnct <- function(df){

  # create output list
  output <- list()

  # define function frqTbl()
  frqTbl <- function(df){

    fctvr <- df[sapply(df,is.factor)]
    logicvr <- df[sapply(df,is.logical)] 
    nwDf <- data.frame(fctvr,logicvr)

    if(ncol(nwDf)>0){ 

      freq <-list() 
      for (i in 1:ncol(nwDf)){ 

        freq[[i]] <- as.data.frame(table((nwDf)[,i]))
        names(freq[[i]])[1]=colnames(nwDf[i])
      } 
      return(freq)
    }
    else{
      print("There are no categorical or logical variables in the data   
          frame.")  
    }
  }

  # call function frqTbl() and store result in list
  output[[length(output)+1]] <- frqTbl(df)

  # define function rSqd()
  rSqd <- function(df){

    y <- df[sapply(df,is.numeric)] 

    if(ncol(y)>=2){ 

      c <- combn(colnames(y), 2) 

      vrPrs <- paste(c[1,], c[2,], sep = "-")

      m <- cor(y, method = "pearson")

      r <- m[which(lower.tri(m))] 

      vlus <- r^2

      df2 <- data.frame(vrPrs, vlus)

      names(df2) <- sub("^vrPrs$", "Variable Pairs", 
                        names(df2)) 
      names(df2) <- sub("^vlus$", "R-Square", names(df2))


      format.data.frame(df2) 
      return(df2)

    }
    else{
      print(paste("This Data Frame does not have two or more numerical  
            columns to compute the Pearson correlation coefficient(s)."))
    }
  }

  # call function rSqd() and store result in list
  output[[length(output)+1]] <- rSqd(df)

  return(output)
}

data(diamonds, package = "ggplot2")
test <- diamonds[1:100,]
mstrFnct(test)