function_name(
argument1 = input_value1,
argument2 = input_value2
)Practice 3: Functions, Objects, Getting Help, Piping, and Import/Export
Let’s work through what you saw in Week 3 together. Rather than treating this as a separate assignment, think of it as picking up where the lessons left off: we’ll walk through the same ideas step by step, and you’ll try each one out for yourself.
Due Sunday, 10/18 at 11pm.
| Lesson | Topic | Video | Slides | What you’ll practice here |
|---|---|---|---|---|
| 13 | Functions | Video | Slides | Functions, Step D |
| 14 | Objects | Video | Slides | Objects, Step D, Step E |
| 15 | Getting help | Video | Slides | Getting help, Step F |
| 16 | Piping | Video | Slides | Piping, Step D |
| 17 | Import and export | Video | Slides | Import and export, Step A, Step C, Step D, Step E |
Functions
Recall from Lesson 13: R has many built-in functions, and most of them look like this:
The arguments are the inputs you hand to the function. For example, seq() makes a sequence of numbers and has three arguments: from (where to start), to (where to stop), and by (the step size).
seq(from = 1, to = 10, by = 2) # 1 3 5 7 9
seq(1, 10, 2) # the same thing: R matches values to arguments by positionTwo more things to remember. c() (short for “combine”) bundles several numbers into one set, like c(1, 2, 3), which is how you give a function a whole list of numbers. And the arrow <- stores a function’s output so you can use it later (more on that in the Objects section).
- In
seq(from = 1, to = 10, by = 2), what arefrom,to, andby?
Look at the “What are functions?” slide in Lesson 13. What does it call the things inside the parentheses?
- Fill in the blanks so
seq()makes the even numbers from 2 to 20:2 4 6 ... 20.
Which number does the sequence start at? Where does it stop? How far apart are the numbers (what is the step)?
seq(from = 2, to = 20, by = 2)
- Because R matches values to arguments by position when you leave the names off, which of these gives the same result as
seq(from = 1, to = 10, by = 2)?
Without names, the order has to match the order from, to, by. See the “We don’t need to specify the argument names” slide in Lesson 13.
- Use
mean()to find the average of these five numbers: 12, 15, 9, 20, and 6. Fill in the blank.
mean() has one main argument, x. It wants all five numbers bundled together as one input.
Use c() to bundle the numbers: c(12, 15, ...).
You run this line in the Console:
odds <- seq(from = 1, to = 10, by = 2)What happens?
Look at the “Output of a function” slide in Lesson 13: The output will not print, but it will be stored in the object.
Objects
Recall from Lesson 14: an object is a stored “thing” in R. You create one with an assignment:
object_name <- valueRead it as “object name gets value.” (= also works, but we use <- in this class.)
Every object has a class, which tells R what kind of thing it is (a number, some text, a date, and so on). The class decides what you can do with the object. For example, you can do math on numbers but not on text. These are the classes you’ll see most often:
| Class | Short | What is it? | Example |
|---|---|---|---|
| Double | dbl |
Numbers | -5.3, 14.5 |
| Integer | int |
Whole numbers | -5, 14 |
| Character | chr |
Text in quotes (no math!) | "My example character" |
| Factor | fct |
Categories with levels | "blue", "red" |
| Logical | lgl |
TRUE or FALSE |
TRUE |
| Date | date |
A date | "12-13-2005" |
The classes above describe one value at a time. An object can also be a collection of many values, such as a vector, matrix, array, data frame (different types of data, in rows and columns), or list. Most datasets are data frames (or their modern cousin, tibbles). The columns of a data frame are called variables, and the $ operator pulls one out: hrs_data$birthyr. The class() function tells you an object’s class.
Several questions below use a tiny, made-up sample called mini_hrs (five “respondents” with a few HRS-style variables). It’s already built for you in each code box, so you don’t need to create it:
| id | age_yr | sex | cesd | ever_smoker |
|---|---|---|---|---|
| R1 | 55 | Female | 2 | TRUE |
| R2 | 62 | Male | 4 | FALSE |
| R3 | 71 | Male | 6 | FALSE |
| R4 | 48 | Female | 0 | TRUE |
| R5 | 67 | Male | NA | FALSE |
(NA means a missing value.)
- How do you read
bp <- 120out loud?
Look at the “How can we create an object?” slide in Lesson 14.
- Fill in the blank with the assignment operator so R stores 38 in an object called
age_years. The next line adds 2 to it.
The assignment operator is an arrow made of two characters. It points at the name.
age_years <- 38
- What is the class of
"42"(with the quotation marks)?
Look at the “Types of objects: single piece of data” slide in Lesson 14. You can also test it: run class(“42”) in your RStudio Console.
A vector can only hold one type of data. What class does R give this vector?
c(1, "a", 3)
The “collection of data” slide in Lesson 14 has a footnote about mixing types. Try class(c(1, “a”, 3)) in your Console.
- Which kind of object holds different types of data (like numbers and text) in rows and columns?
Look at the “Types of objects: collection of data” table in Lesson 14.
- How is a tibble different from a regular data frame?
Look at the “Data frames and tibbles” slide in Lesson 14.
- Use
$to pull out thecesdcolumn ofmini_hrs, and useclass()to find its class. Fill in the blank with the column name.
$ goes between the data frame’s name and the column’s name, and the column name is already written after it. What’s the column called? (See the table above.)
class(mini_hrs$cesd)
- Run the code below as it is. R doesn’t give an error, but you get
NAand a warning. Read the warning, then fix the code so it gives the mean age of the five people inmini_hrs.
The warning says Unknown or uninitialised column: Age_yr. Compare the name to the column names in the table above.
R is case-sensitive: Age_yr and age_yr are different names.
Here’s some code and what R printed:
ages <- c(55, 62, 71, 48, 67) mean("ages")[1] NA Warning message: In mean.default("ages") : argument is not numeric or logical: returning NAWhy did this happen?
Look at the warning: argument is not numeric or logical. What does putting something in quotes do (Question 8)?
Getting help
Lesson 15 said it plainly: a huge part of coding is learning to figure out what’s going wrong. When you’re stuck, try these steps in order:
| Step | What to do | Best for |
|---|---|---|
| 1 | Use ?function_name to read the function’s help page |
Understanding a function’s arguments and usage |
| 2 | Google the exact error message (add “in R”) or check Stack Overflow | Specific errors and edge cases |
| 3 | Ask an AI tool | Explaining errors or getting code started |
| 4 | Ask a person, with a reprex | When all else fails |
Every help page has the same sections: Description, Usage, Arguments, Value, and Examples. The Arguments and Examples sections are the most useful for beginners.
- Which of these open the help page for the
mean()function? Select all that apply.
Look at the “R Documentation with ?” slide in Lesson 15. Two of these do exactly the same thing. The other two do something a little different.
- You want to round
3.14159to 2 decimal places. Fill in the blank with the right number.
Try it in your RStudio Console first: round(3.14159, digits = 2). How many decimal places do you want? Put that number in the blank.
round(3.14159, digits = 2)
- By default,
mean()returnsNAif even one value is missing. Fill in the blank with the argument that tellsmean()to removeNAs, so you get the average of the four ages we have.
Not sure? Check ?mean in your RStudio Console. The argument’s name has two parts, separated by a dot. It stands for “NA remove”. You set it to TRUE.
mean(ages, na.rm = TRUE)
- You run
5 + "10"and seeError in 5 + "10" : non-numeric argument to binary operator. Which Google search is most likely to help?
Look at the “Google and Stack Overflow” slide in Lesson 15 for tips on a good search.
- You find a Stack Overflow answer. Which things should you check before trusting it? Select all that apply.
Look at the “Reading Stack Overflow answers” box on the “Google and Stack Overflow” slide in Lesson 15.
- Our course policy allows AI to help you understand, but it shouldn’t do the problem for you. Which of these are good uses of AI on a practice? Select all that apply.
Look at the AI slides in Lesson 15 and the Generative AI Policy. Could you explain every line of your submitted code?
- A good reprex (reproducible example) makes it easy for someone else to help you. Which of these belong in a good help request? Select all that apply.
Look at the “Getting help from someone” slide in Lesson 15. A reprex should be self-contained and minimal: include what’s needed, but no more.
- Which of these help requests would be easiest for an instructor or classmate to answer?
Look at the “Demo: Writing a reprex” slide in Lesson 15. Which request has context, a small amount of data, and the exact code?
You’ll write your own help request in Step F.
Piping
Lesson 16: a pipe passes the output of one function into the next function. Think of |> as the word “then.”
# Nested: you read it from the inside out
round(mean(c(10, 20, 35)), digits = 1)
# Piped: you read it left to right
c(10, 20, 35) |>
mean() |>
round(digits = 1)|>is the newer pipe built into R (no package needed).%>%is the original pipe from themagrittrpackage (loaded withtidyverse). Either works; this class uses|>.- By default, the piped value goes into the first argument of the next function. When it needs to go somewhere else, you use a placeholder:
_for|>(and.for%>%). For example,3 |> seq(from = 1, to = 10, by = _)puts the 3 inby. - Start a new line after each pipe so your code is easy to read.
- Which pipe does the same thing as the nested code
round(mean(c(10, 20, 35)), digits = 1)?
In nested code, the innermost function runs first. What does the pipe version need to do first? See the “What is piping?” slide in Lesson 16.
- Fill in the blank so the pipe takes the square root of each number, then adds them up. (You only need the function’s name: the parentheses are already there.)
What do you want to happen to each number before adding them? There’s a function for it that you’ve used before.
The function is sqrt. The square roots are 2, 3, and 4.
- Here, the
3is piped intoseq(), but we want it to land in thebyargument, not the first one. Fill in the blank with the placeholder for|>.
The placeholder for |> is a single character. (The other pipe, %>%, uses a dot instead.)
3 |> seq(from = 1, to = 10, by = _)
- R reads each line and runs it as soon as the line looks finished. Run the code below as it is and read the error. Then fix it so the pipe works.
The error says unexpected '|>'. R thought c(4, 9, 16) was a complete line, so the next line started with a pipe it didn’t expect.
End the first line with the pipe, so R knows to keep reading: c(4, 9, 16) |>.
- What is the placeholder for the native pipe
|>?
Look at the “Simple vs complicated input” slide in Lesson 16.
You’ll use a pipe on the real HRS data in Step D.
Import and export
Lesson 17: to work with a dataset, you bring it into R with an import function. Which one depends on the file type:
| File type | Extension | Function | Package |
|---|---|---|---|
| CSV | .csv |
read_csv() |
readr |
| Excel | .xlsx |
read_excel() |
readxl |
| RDS | .rds |
read_rds() |
readr |
| SAS | .sas7bdat |
read_sas() |
haven |
| Stata | .dta |
read_dta() |
haven |
The rio package gives you one function, import(), that figures out the file type from the extension, and export() to save. We build file paths with here() (Lesson 12), so they work no matter where your file lives. For example:
hrs_data <- import(here("data_practice", "hrs_data.rds"))
export(hrs_data, here("data_practice", "hrs_data_clean.csv"))You’ll import the real HRS data on your own computer in the steps at the end. (This page can’t read files from your computer, so the questions here are about how to do it.)
- Which function reads an Excel (
.xlsx) file into R?
Look at the “Functions to import different file types” slide in Lesson 17.
- How does
import()fromrioknow which kind of file it’s reading?
Look at the “rio package” slide in Lesson 17.
- You want to save a cleaned dataset so that every variable keeps its exact type (like factors) the next time you open it in R. Which file type is best?
Look at the “Exporting data” slide in Lesson 17: Prefer .rds for saving R objects between sessions.
- Use
here()to build the path tohrs_data.xlsx, which lives in thedata_practicefolder of your course folder. Separate the folder and file names with a comma.
Put each name in quotes, folder first, then the file: "folder", "file.ext".
here("data_practice", "hrs_data.xlsx")
- Which line exports
hrs_dataas a.csvfile in thedata_practicefolder?
Look at the “Exporting data” slide in Lesson 17: the object comes first.
- Real datasets often have messy variable names (spaces, capital letters).
clean_names()from thejanitorpackage fixes them. Thejanitorpackage is already loaded on this page. Fill in the blank with the function that cleans the names ofmessy.
The function has two words joined with an underscore: first the word that means “tidy up,” then “names.”
clean_names
You run
import(here("data_practice", "hrs_data.rds"))and get:Error in import(...) : could not find function "import"What is the most likely problem?
Look at the “Function not found, package not loaded” slide in Lesson 9 and the note about rio on the “rio package” slide in Lesson 17.
AI Use Statement
Using AI is not required in this class. If you did use an AI tool (ChatGPT, Claude, Copilot, Gemini, an RStudio assistant, etc.) on this practice, add a brief AI Use Statement. Include:
- Which tool(s) you used
- What for (a sentence or two, with question numbers)
- Where it contributed to any written answers (if at all)
- You do NOT need to link your conversation.
For example:
AI Use Statement: Claude was used to explain an error message in Question 13. All reasoning and answers are my own.
OR
AI Use Statement: AI was not used in this assignment.
Before using AI, check the table of allowed uses in the Generative AI Policy. For practice, AI can help you understand (explain an error or a concept, explain what a function does, check an answer you already worked out), but it should not do the problem for you. A half-finished answer that shows your thinking is always better than a polished one from AI!
Fill in your statement below. It’s saved as you type, and it goes at the top of your downloaded .qmd, right where your submission needs it.
Your turn: working with real data
Now let’s put this week together in RStudio, with the real HRS data. These steps are ungraded self-check, but your downloaded .qmd (and the .html you render from it) is what you turn in. Do them in order: Step A first, and open your R Project (double-click PUBH_523_26F.Rproj) before you start.
Step A: Get the data and file it
(Lessons 5 and 17) Download hrs_data.rds and save it in the data_practice folder of your PUBH_523_26F course folder (the one from Lesson 5). Check that the file name still ends in .rds (some browsers add .txt or a number). You don’t need the Excel version for the steps below, but if you’d like to try read_excel() on your own, hrs_data.xlsx is in the same place on GitHub.
Step B: Download your answers, open them, and load packages
Click Download my answers as .qmd (the button in the sidebar, or at the bottom of the last section, Step G). Move the file into PUBH_523_26F/practice/, and rename it lastname_firstinitial_practice_03.qmd. In RStudio (with your project open), open it from the Files pane. Change author: in the YAML to your name.
Then find the Load packages chunk near the top of the file and type this inside it:
pacman::p_load(tidyverse, here, rio, janitor)rio is new this week, so the first time may take a minute or two while it installs. Run the chunk (Ctrl + Enter / Cmd + Enter on the line) to be sure it works. Don’t render yet!
Step C: Your first render fails on purpose
(Lessons 12 and 17) In your .qmd, scroll to the Import and export (Lesson 17) section and find the chunk labeled Step C. It has this line:
hrs_data <- read_rds("data_practice/hrs_data.rds")Now click Render. It will stop with an error that says Error in `readRDS()`: ! cannot open the connection, and a warning that mentions data_practice/hrs_data.rds and No such file or directory. When you render, R starts in the practice/ folder, so it looked for practice/data_practice/hrs_data.rds, which doesn’t exist. (This is the same reason getwd() and here() disagreed in Practice 2.)
To fix it, inside that chunk, build the path with here(), using commas to separate the folder name and the file name (Lesson 12, and Question 31). Here’s the shape. Fill in each ______ with the folder and file names from the broken line above:
hrs_data <- read_rds(here(______, ______))Render again. It should work this time.
Step D: Import with rio, pipe into clean_names(), and look at the data
(Lessons 14, 16, and 17) In the Import and export (Lesson 17) section, find the chunk labeled Step D. Inside the chunk, write code that does four things: (1) imports hrs_data.rds with a here() path, (2) pipes the data into the function that cleans the variable names, (3) finds the number of rows and columns, and (4) checks the class of the degree column. Here’s a partial version to build from. Replace each ______ with the missing function or name (all of them came up in this week’s questions or lessons):
hrs_data <- ______(here("data_practice", "hrs_data.rds")) |>
______()
hrs_data |> ______()
class(hrs_data$______)If it works, you’ll see 2728 and 32 for the rows and columns, and the class of degree will be factor. Below the chunk (as regular text, not in the chunk), write 1–2 sentences: what did the pipe do in the first line of code?
Step E: Export, re-import, and compare
(Lesson 17) In the Import and export (Lesson 17) section, find the chunk labeled Step E. Inside the chunk, write code that (1) saves hrs_data as a .csv file called hrs_data_export.csv in data_practice, (2) reads that file back in as a new object called hrs_data_csv, and (3) compares the class of the degree column in the two data sets. Here’s a partial version. Replace each ______:
______(hrs_data, here("data_practice", "hrs_data_export.csv"))
hrs_data_csv <- ______(here("data_practice", "hrs_data_export.csv"))
class(hrs_data$degree)
class(hrs_data_csv$______)You’ve just saved a .csv and read it back. Below the chunk (as regular text), write 1–2 sentences: did the class of degree stay the same? Why do you think that happened, and what does it tell you about when to save as .rds instead of .csv? (Check your data_practice folder: your new .csv should be there.)
Step F: Practice getting help
(Lesson 15) First, type ?round in the Console and scroll to the Examples section at the bottom of the help page. Then, in your .qmd, scroll to the Getting help (Lesson 15) section and find Step F. Imagine you couldn’t solve Question 13 (the Age_yr problem). Below the chunk labels (as regular text), fill in what you expected, what actually happened, and the exact warning message. Then, inside the chunk, write a small reprex: the packages, the tiny made-up data (a few rows is enough), and the exact code that causes the problem. Leave #| eval: false in the chunk so it doesn’t run when you render. (Do this after Step E, since it comes later in your file than the Lesson 17 section.)
Step G: Render and submit
Render one last time. Check that your AI Use Statement shows at the top of the .html. Then submit both your .qmd and .html on Brightspace.
Didn’t finish every question? That’s okay! Practice is graded on completion: you get credit for answering at least 75% of the question parts, whether your answers are right or wrong. Anything you haven’t finished shows up as Not answered yet or Not finished yet in your download, and won’t stop your file from rendering.
Check your overall progress on this practice set on the My Progress page.