Title image Spring 2022

More Useful Functions

The purpose of this project is to look at some more useful functions that are part of R and to practice some of the things you've learned previously. Each task addresses separate features of R, so you should keep your code organized by encapsulating the code for each task into one or more functions. For example, the first function required in task 1 is FixMixed_v1, so you will begin with code like this:

fixMixed_v1 <- function( ) {
  # code for task 1B goes here

  # have the function return the data frame created/read in this function
}

Project Tasks

    Part 0: Setup

    Get ready to write some R code and write a function to read data.

    Open R Studio or a text editor and Create a new R file called project4.R. Put your name, Project 4, and the date at the top of the file. Save your file to an appropriate working directory.

    Part 1: Fixing up Data

  1. Eventually, we all have to deal with reading in data that has missing values or that R interprets differently from how we want to use it. There are many functions we can use to explore our data, making sure it matches what we want. In cases where it does not, we can either manually fix the problems or try adding arguments to the read function that avoid the problems.
    1. Download the file mixed.csv. Store it in the same directory as your project4.R file. Set the working directory to your source file location.
    2. Create a function called fixMixed_v1 to encapsulate this task, as specified above. Add code to the function and test it by completing the following sub-tasks.

      1. This function is specific to a particular data file and it will achieve a particular goal, namely ensuring the Apple column is numeric. It is good practice to use a function name that indicates the function's purpose (which we do here - sort of - we specify that the file is mixed and that we are fixing it up, but not what or how we are fixing it up - also we indicate that it is the first version of the function with v1). It is also good practice to write a comment at the beginning of each function, indicating what it does and what it returns. Add this comment before writing any code:
          # Read in mixed.csv and change the $Apple column to be all numeric.
          # Return the dataframe with the adjusted data.
        
      2. Assign to a variable the data frame generated by calling the read.csv() function to read the mixed.csv file.
      3. Before we write code to fix up the file, it is a good idea to print out what is in the file. The next few tasks are designed to get you in the habit of printing information out. We can't write the fix-up code without knowing what we are fixing. :)

      4. Print the result of calling the str() function with the data frame as the argument to print out a representation of the data frame.
      5. Add a call to fixMixed_v1 at the bottom of the file and Source the file to run it and test it.
      6. Print the result of calling the summary() function on the data frame to print out a summary of the data in the data frame.
      7. Source the code to test it again.
      8. Use a for loop to loop over the columns of the data frame. You can do this using either syntax below.
        #option 1
        for( column in myDataFrame ) {
           # code to repeat goes here, column refers to each column in turn
        }
        
        #option 2
        for(i in 1:length(myDataFrame) ) {
           # code to repeat goes here, myDataFrame[[i]] refers to each column in turn
        }

        Each time through the loop, print the result of applying the class() and the typeof() functions to the current column. Note that three of the columns are character strings, including the first one. See if you can write out the name of each column along with its class and type (it's easier to use the second option for loop to do this).

      9. Source the code to test it again.
      10. Now, we finally again to the stated purpose of the function. Re-assign the "Apple" column to be numeric. To do this, you have to first convert the column to a character column using as.character(), then convert the column to a double column using as.double(). You can compose the two functions and assign the result back to the "Apple" column in a single line.
      11. On the last line, return the data frame.
      12. Update the test code to assign the return value to a variable and print out its contents by calling the str() function.
      13. df <- fixMixed_v1()
        print( str( df ) )
        

        It should show Apple as a numeric column.

    3. Write a second function, fixMixed_v2 that will use an alternate approach to fixing the Apple column and which will make the Banana column contain strings.
      1. Add comments to reflect this purpose:
          # Read in mixed.csv and change the Apple column to be all numeric.
          # Also change the Banana column to be a character vector.
          # Return the dataframe with the adjusted data.
        
      2. Read in the data using read.csv, assigning the data frame to a variable. This time use the na.strings parameter and give it the value c("NA", ".").
      3. Print the result of calling the str() on the data frame to note the difference.
      4. Add code to call fixMixed_v2 to the bottom of the file and Source it to test it.
      5. Convert the "Banana" column to a character vector using as.character().
      6. On the last line, return the data frame
      7. Update the test code to assign the return value to a variable and print out its contents by calling the str() function.
      8. df <- fixMixed_v2()
        print( summary( df ) )
        
  2. Part 2: Exploring which and seq

  3. Practice logical indexing with two helpful functions: The which function lets you select data based on a test. The seq function lets you create sequences of numbers with different patterns.

    1. Create a function called learnWhich to encapsulate code that uses the which function. The function should have one parameter, which is the data fram to use.

      Add a comment indicating the purpose of this function is to give you practice with which and that the dataframe parameter is expected to have the fixed up data from mixed.csv in it.

      The which() function takes in a logical vector and returns the set of indices corresonding to the TRUE elements of the vector. An expression like myDataFrame$Apple < 5 generates a logical vector. See what happens when you pass it to which().

      which(myDataFrame$Apple < 5)

      Use the which function to assign to the variable indexes the set of indices of the values of the Pear column that are less than 50. Print out the indexes variable and double-check that it is correct. To double-check it, print out the Pear column and use indexes to select that subset of the data (e.g. myDataFrame$Pear[indexes]. All of the values should be less than 50.

      Update your test code to call this function, and Source it to test it. Note (you many want to comment out any print functions in fixMixed_v2 so that your Console is not cluttered.)

      df <- fixMixed_v2()
      learnWhich( df )
      
    2. Create a function called learnSeq to encapsulate code that uses the which function. The function should have one parameter, which is the data fram to use.

      Add a comment indicating the purpose of this function is to give you pract ice with which and that the dataframe parameter is expected to have the fixed up data from mixed .csv in it.

      The seq() function takes in one, two, or three arguments and allows you to generate sequences of numbers. The three argument version takes in the starting value, the ending value, and the step value. Use the seq() function to assign to the variable indexes2 the values from 1 to 10 in steps of 3. Use indexes2 to print out that subset of the Pear column. You should get the values at position 1, 4, 7, and 10.

      Add test code to the bottom of the file and Source it to test it now, and after each new line of code is added.

      Print out the values in the Apple column at odd indices (i.e. 1, 3, etc.) using seq to generate the indexes.

      Print out the values between 4.5 and 5.5 in the Apple column using whatever method you like.

  4. Part 3: Adding Decorations to Plots

  5. Explore adding arrows, text, and lines to a plot.

    There are many other capabilities built into the R base plotting system. One of these is the ability to put lines, text, and arrows into a plot.

    Create a function called decorateSizePlot to ecapsulate this task. The function should have one parameter, which is the data frame to use. This function does not need to return anything explicitly. Be sure to test it as you add features to the plot (add code to the bottom following the pattern of previous tasks).

    1. Write a comment at the beginning of the function indicating that this function makes a barlplot from the Size column of the data frame and annotates it with an arrow and text.
    2. Make a bar plot using the Size column (don't forget to use the table function). Adjust the amount of space between the columns and specify the x-axis label and main title.
    3. Use the arrows() function to add an arrow to the plot pointing at the small bar.
    4. Use the text() function to add some text at the tail of the arrow saying "There are lots of small fruits".
    5. Use the lines() function to add a blue line of width 2 underneath the text.

  6. Part 4: Exploring Random Numbers

    Explore generating different kinds of random numbers.

  7. Generating random numbers from uniform or normal distributions can be extremely useful for a wide variety of applications. For this task, you will create random numbers and view their distributions using a histogram.

    Create a function called plotRandomDistributions to encapsulate this task. The function should have one optional parameter, N, which is the number of points to use. Give the N parameter a default value of 1000. Inside the function, write code to do the following tasks. This function does not need to return anything explicitly. As with the previous tasks, test as you go.

    1. Assign to the variable flat the result of using the runif() function to generate a vector of N uniformly distributed numbers in the range 0 to 100.
    2. Assign to the variable bump the result of using the rnorm() function to genreate a vector of N normally distributed numbers with a mean of 50 and a standard deviation of 10.
    3. Generate a histogram plot of the uniformly distributed numbers. Use the argument xaxt='n' to tell the hist() function not to generate an X-axis. Then use the axis() function to create a new X-axis.
    4. Generate a histogram plot of the normally distributed numbers. As with the prior step, create your own X-axis with customized features like a smaller font size (e.g. cex.axis parameter).

    Once you have completed and tested the plotRandomDistributions function, at the end of your R file call it 3 times: once with the argument 100, once with no argument, and once with the argument 10000. Save one of the plots of the normal distribution and hand it in with your code.


Report

Answer the following questions. Submit your answers as a plain text file or PDF in your handin directory. Put your name at the top of the file. No credit will be given for any other format or for a file without a name.


Turn In