Functions, For Loops, and Conditionals in R

Viewed 585

I'm given a .csv data set and I want to establish a function for the data using a for loop. The data set has 5 columns, data consisting of either factors or numerics. If the data is a factor, nothing should be done, just print out the name of the column and it's class. If the data is numeric, then print out the name, class, as well as two functions (that I had already created beforehand).

I'm a bit lost on how to go about organizing the syntax for the function/for loop.

p.data <- read.csv("file.csv")
function(
x){
for.loop.variable <- for(index in data.csv){
if (class(x)) == "factor" 
{cat("Name of Column is:", names(x*), "\n", 
"Class of Column is :" , (class(x)))
} else {
cat("Name of Column is:", names(x*), "\n", 
"Class of Column is :" , (class(x)),"\n", 
"Function 1 is :", function.1(x), "\n",
"Function 2 is :", function.2(x), "\n")
}
}
}
return (for.loop.variable)

I think that's the right set up but I have 3 questions that I can't seem to figure out:

1- How does the for loop iteration come into play? I hadn't referenced it in the conditionals at all and I'm not sure how to go about doing so?

2*- How do I go about calling/printing the column name? I don't think it's names(x) but I'm not too sure what it would be other than that.

3- Is the return () correct? Should it return the entire for loop (once I figure out how to tie it into the actual problem) from the variable?

Please let me know where to fix errors so I can properly learn this, please.

Here's an image of the example code so it's a bit easier to read as far as brackets/syntax goes: enter image description here

5 Answers

I assume this question is for educational purposes and therefore present a simple for loop:

class_print <- function(df){

  for(i in 1:ncol(df)){
    if(is.factor(df[,i])){
      print(paste0("Name of column is ", names(df[i]), "class is factor ",collapse = ""))
    }
    else{
     print(paste("Name of column is ", names(df[i]),"class is ", class(df[,i]),collapse=""))
    }

  }

}

Testing:

class_print(iris)
[1] "Name of column is  Sepal.Length class is  numeric"
[1] "Name of column is  Sepal.Width class is  numeric"
[1] "Name of column is  Petal.Length class is  numeric"
[1] "Name of column is  Petal.Width class is  numeric"
[1] "Name of column is Speciesclass is factor "

You were missing some parenthesizes that look like they got moved to the wrong spot. I took your code and cleaned it up to help you compare.

Since cat in R prints right to the console, you don't need to necessarily use return, actually when I tested it, return made it so only the last iteration of the loop printed.

 p.data <- read.csv("file.csv")
 for(i in seq_along(p.data)){
     x <- p.data[,i] #pull the individual column for this current iteration

    if (class(x) == "factor"){
        cat("Name of Column is:", x, "\n", 
            "Class of Column is :" , (class(x))
            )
                              } else {
        cat("Name of Column is:", x, "\n", 
            "Class of Column is :" , (class(x)),"\n",
            "Function 1 is :", function.1(x), "\n",
            "Function 2 is :", function.2(x), "\n")
                                      }
                            }

Doing this in a for loop in R is alright. Depending on who you ask you might get told that for loops in R as very slow. This is kind of true, if you are building a dataframe or a vector without preallocating the object memory it will be very slow.

Another tool you can use is walk from the package purrr but since you asked for a for loop I did it in a for loop, I will make up a walk version and update it

walk(p.data, function(x){
    if (class(x) == "factor"){
     cat("Name of Column is:", names(x), "\n", 
         "Class of Column is :" , (class(x)))
                             } else {
  cat("Name of Column is:", names(x), "\n", 
      "Class of Column is :" , (class(x)),"\n"),
      "Function 1 is :", function.1(x), "\n",
      "Function 2 is :", function.2(x), "\n")
   }
  }
 )

This code prints the result below.

# Sample data
p.data <- data.frame(A = letters[1:5], B = 5:1, C = 1:5, D = LETTERS[5:9], stringsAsFactors = TRUE)

# sample function
function.1 <- mean
function.2 <- sum

# If the data is a factor, nothing should be done, just print out 
# the name of the column and it's class. If the data is numeric, 
# then print out the name, class, as well as two functions
Descr <- function( x ) {
  for(index in 1:ncol(x)) {
      if (is.factor(x[[index]])) {
        cat("Name of Column is:", names(x[index]), "\n", 
            "Type of Column is :" , class(x[index]), "\n")
      } else {
        cat("Name of Column is:", names(x[index]), "\n", 
            "Type of Column is :" , (class(x[index])),"\n", 
            "Function 1 is :", function.1(x[[index]]), "\n",
            "Function 2 is :", function.2(x[[index]]), "\n")
      }
  }
}

Descr(p.data)

Name of Column is: A
Class of Column is : data.frame
Name of Column is: B
Class of Column is : data.frame
Function 1 is : 3
Function 2 is : 15
Name of Column is: C
Class of Column is : data.frame
Function 1 is : 3
Function 2 is : 15
Name of Column is: D
Class of Column is : data.frame

Note that the class is always 'data frame'. You have to specify wht exactly you need to know.

I was going to start you out a little slower here are some basics.

p.data <- mtcars
p.data$cyl <- factor(p.data$cyl)

for (i in seq_along(colnames(mtcars))) {

#  print(colnames(p.data)[[i]])

  if (class(p.data[[i]]) == "factor") {
    print(colnames(p.data)[[i]])
  } else {
    print("nope")
  }

}
#> [1] "nope"
#> [1] "cyl"
#> [1] "nope"
#> [1] "nope"
#> [1] "nope"
#> [1] "nope"
#> [1] "nope"
#> [1] "nope"
#> [1] "nope"
#> [1] "nope"
#> [1] "nope"

Created on 2020-05-11 by the reprex package (v0.3.0)

FunctionName <- function(x){
   for (col_n in 1:ncol(x)){
      if (class(x[col_n]=="factor"){
         cat("Name of Column is:", names(x[col_n]), "\n", 
             "Class of Column is :" , (class([col_n])))
      } else {
        cat("Name of Column is:", names(x[col_n]), "\n", 
            "Class of Column is :" , (class(x[col_n])),"\n", 
            "Function 1 is :", function.1(x[,col_n]), "\n",
            "Function 2 is :", function.2(x[,col_n]), "\n")
      }
   }
}

1- How does the for loop iteration come into play? I hadn't referenced it in the conditionals at all and I'm not sure how to go about doing so? I'm not clear on your question here, but I believe you are asking here what is being iterated. Your iterator here is the explicit row of the data.csv (stored as a data.frame or data.table). Based on context, I think you want to be reading the file into the function (as x) that way when you then go through your print statements, you are actually printing what is being looped.

2*- How do I go about calling/printing the column name? I don't think it's names(x) but I'm not too sure what it would be other than that. The way you have the function written, this would be a bit difficult to do. Check out my code for an example of how I would go about this. In my code, x is the data.csv (stored as a data.frame or data.table) and would only print messages to the screen. I also assumed your functions required the input of the entire column - so that might need some finagling on your end.

3- Is the return () correct? Should it return the entire for loop (once I figure out how to tie it into the actual problem) from the variable? This depends a bit on what you want returned. The way you have it set up I'm not clear on what would be the output. Your goal sounds like you just want information printed to the screen. If instead you want to make a variable with all of the messages, you could then store each message as a line in the variable and output that as you have written.

Related