Introduction to R Programming

NRES Capstone Workshop

Manoj Sharma

2026-03-03

What is R?

  • R is a free, open-source programming language
  • Designed specifically for statistics and data analysis
  • Used by data scientists, researchers, and analysts worldwide
  • Huge community → lots of free help online!

Why learn R?

✅ Free forever
✅ Powerful graphics
✅ Thousands of packages
✅ Reproducible research
✅ High demand in job market

R vs. R Studio

R RStudio
What it is The engine The car dashboard
Function Runs your code Makes coding easier
Can you use alone? Yes No (needs R)
Recommended? Install first Use this daily

Tip

Think of R as the engine and RStudio as the car. You need both!

Step 1: Download R

  1. Open your browser and go to https://cran.r-project.org
  2. Click “Download R for Windows”
  3. Click “base”
  4. Click “Download R-4.5.2 for Windows” (latest version)
  5. Open the downloaded .exe file
  6. Click Next -> Next -> Install (keep all defaults!)

Important

Always install the latest version of R.

Step 2: Download RStudio

  1. Go to https://posit.co/download/rstudio-desktop/
  2. Scroll down to find “2: Install RStudio”
  3. Click “Download RStudio for Windows”
  4. Open the downloaded .exe file
  5. Follow the installation wizard (keep all defaults)
  6. Launch RStudio from your Start Menu

Note

Posit is the company that makes RStudio. It’s completely free!

Verify Your Installation

Open RStudio and type this in the Console panel:

R.version.string

Tip

If you see a version number – congratulations! R is installed correctly 🎉

The RStudio Interface

+---------------------+---------------------+
|                     |                     |
|   Source Editor     |   Environment /     |
|   (Write scripts)   |   History           |
|                     |                     |
+---------------------+---------------------+
|                     |                     |
|   Console           |   Files / Plots /   |
|   (Run code here)   |   Packages / Help   |
|                     |                     |
+---------------------+---------------------+

The 4 Panels Explained

  • Where you write and save your R scripts
  • Files end in .R or .qmd
  • Press Ctrl + Enter to run a line of code
  • Where code actually runs
  • You can type directly here
  • Shows output and error messages
  • Shows all your variables and data
  • Tracks what’s currently in memory
  • Use the broom 🧹 icon to clear it
  • Browse your file system
  • View plots and graphs
  • Install and manage packages

Setting Your Working Directory

The working directory is the folder where R looks for files.


# Check your current working directory
getwd()

# Set a new working directory
setwd("C:/Users/Manoj/OneDrive - Kansas State University/00_NRES_research_project")

# Better way: Use RStudio Projects!
# File -> New Project -> New Directory

Tip

Best Practice: Always use RStudio Projects (.Rproj files). They automatically set your working directory!

Installing Your First Package

Packages are add-ons that extend R’s capabilities.

# Install a package (only do this ONCE)
install.packages("tidyverse")

# Load a package (do this EVERY session)
library(tidyverse)

# Check what packages are installed
installed.packages()[, "Package"]

Warning

install.packages() = download from internet (once)
library() = load into session (every time you open R)

R as a Calculator

# Basic arithmetic
2 + 3        # Addition -> 5
[1] 5
10 - 4       # Subtraction -> 6
[1] 6
3 * 7        # Multiplication -> 21
[1] 21
15 / 4       # Division -> 3.75
[1] 3.75
2 ^ 3        # Exponentiation -> 8
[1] 8
17 %% 5      # Remainder -> 2
[1] 2
17 %/% 5     # Integer division -> 3
[1] 3

Note

The # symbol creates a comment. R ignores everything after # on a line.

Variables & Assignment

# Assign values using <- (preferred) or =
my_name <- "Alice"
age <- 20
gpa <- 3.85
is_student <- TRUE

# View the value
my_name        # Prints: "Alice"
[1] "Alice"
print(age)     # Also prints: 20
[1] 20
# Check what's in your environment
ls()
[1] "age"             "gpa"             "is_student"      "my_name"        
[5] "pandoc_dir"      "quarto_bin_path"

Tip

Shortcut: Press Alt + - to type <- automatically in RStudio!

Naming Rules for Variables

✅ Valid names:

my_variable
myVariable
data1
x
total_score_2024

❌ Invalid names:

1variable    # starts with number
my-variable  # has hyphen
my variable  # has space
TRUE         # reserved word

Tip

Use snake_case (words separated by underscores) – it’s the most readable style in R!

Data Types in R

# Numeric (numbers)
score <- 95.5
class(score)       # "numeric"
[1] "numeric"
# Character (text/strings)
name <- "John"
class(name)        # "character"
[1] "character"
# Logical (TRUE/FALSE)
passed <- TRUE
class(passed)      # "logical"
[1] "logical"
# Integer
count <- 42L       # The L makes it an integer
class(count)       # "integer"
[1] "integer"

Checking & Converting Data Types

# Check type
is.numeric(3.14)      # TRUE
[1] TRUE
is.character("hello") # TRUE
[1] TRUE
is.logical(FALSE)     # TRUE
[1] TRUE
# Convert between types
as.numeric("42")      # 42
[1] 42
as.character(100)     # "100"
[1] "100"
as.logical(0)         # FALSE
[1] FALSE
as.logical(1)         # TRUE
[1] TRUE
# What happens with invalid conversion?
as.numeric("hello")   # NA (with a warning!)
[1] NA

Vectors: R’s Building Block

A vector is a sequence of values of the same type.

# Create vectors with c() -- "combine"
grades <- c(85, 92, 78, 96, 88)
names  <- c("Alice", "Bob", "Carol")
passed <- c(TRUE, TRUE, FALSE, TRUE)

# Useful shortcuts
1:10                  # 1 2 3 4 5 6 7 8 9 10
 [1]  1  2  3  4  5  6  7  8  9 10
seq(0, 1, by = 0.25)  # 0.00 0.25 0.50 0.75 1.00
[1] 0.00 0.25 0.50 0.75 1.00
rep(0, times = 5)     # 0 0 0 0 0
[1] 0 0 0 0 0

Working with Vectors

grades <- c(85, 92, 78, 96, 88)

# Basic statistics
length(grades)   # 5
[1] 5
sum(grades)      # 439
[1] 439
mean(grades)     # 87.8
[1] 87.8
max(grades)      # 96
[1] 96
min(grades)      # 78
[1] 78
sd(grades)       # standard deviation
[1] 6.870226
# Indexing (R starts at 1, not 0!)
grades[1]        # 85 (first element)
[1] 85
grades[2:4]      # 92 78 96 (elements 2 to 4)
[1] 92 78 96
grades[-1]       # All EXCEPT first element
[1] 92 78 96 88

Comparison Operators

# These return TRUE or FALSE
5 > 3       # TRUE
[1] TRUE
5 < 3       # FALSE
[1] FALSE
5 == 5      # TRUE  (note: double equals!)
[1] TRUE
5 != 3      # TRUE  (not equal)
[1] TRUE
5 >= 5      # TRUE
[1] TRUE
5 <= 4      # FALSE
[1] FALSE
# With vectors (applied to each element)
grades <- c(85, 92, 78, 96, 88)
grades > 80   # TRUE TRUE FALSE TRUE TRUE
[1]  TRUE  TRUE FALSE  TRUE  TRUE
grades[grades > 80]   # 85 92 96 88
[1] 85 92 96 88

Logical Operators

# AND: both must be TRUE
TRUE & FALSE    # FALSE
[1] FALSE
5 > 3 & 10 > 7  # TRUE
[1] TRUE
# OR: at least one must be TRUE
TRUE | FALSE    # TRUE
[1] TRUE
5 > 3 | 2 > 10  # TRUE
[1] TRUE
# NOT: flips TRUE/FALSE
!TRUE           # FALSE
[1] FALSE
!FALSE          # TRUE
[1] TRUE
# Practical example
grades <- c(85, 92, 78, 96, 88)
grades[grades > 80 & grades < 95]   # 85 88 92
[1] 85 92 88

If / Else Statements

score <- 75

# Basic if-else
if (score >= 60) {
  print("Pass")
} else {
  print("Fail")
}
[1] "Pass"

Multiple Conditions

if (score >= 90) {
  grade <- "A"
} else if (score >= 80) {
  grade <- "B"
} else if (score >= 70) {
  grade <- "C"
} else {
  grade <- "F"
}
print(grade)   # "C"
[1] "C"

For Loops

# Basic for loop
for (i in 1:5) {
  print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
# Loop over a vector
fruits <- c("apple", "banana", "cherry")
for (fruit in fruits) {
  print(paste("I like", fruit))
}
[1] "I like apple"
[1] "I like banana"
[1] "I like cherry"
# Practical: calculate squares
squares <- c()
for (i in 1:5) {
  squares <- c(squares, i^2)
}
print(squares)   # 1 4 9 16 25
[1]  1  4  9 16 25

Functions

# Using built-in functions
sqrt(16)        # 4
[1] 4
abs(-7)         # 7
[1] 7
round(3.14159, digits = 2)   # 3.14
[1] 3.14
toupper("hello")  # "HELLO"
[1] "HELLO"
# Writing your OWN function
say_hello <- function(name) {
  message <- paste("Hello,", name, "!")
  return(message)
}

say_hello("Alice")   # "Hello, Alice !"
[1] "Hello, Alice !"
# Function with default argument
greet <- function(name, greeting = "Hello") {
  paste(greeting, name)
}
greet("Bob")              # "Hello Bob"
[1] "Hello Bob"
greet("Bob", "Hi there")  # "Hi there Bob"
[1] "Hi there Bob"

Data Frames: The Heart of Data Analysis

# Create a data frame
students <- data.frame(
  name  = c("Alice", "Bob", "Carol", "David"),
  age   = c(20, 22, 21, 23),
  grade = c(92, 85, 78, 96),
  pass  = c(TRUE, TRUE, TRUE, TRUE)
)

# View the data
students           # Print the whole table
   name age grade pass
1 Alice  20    92 TRUE
2   Bob  22    85 TRUE
3 Carol  21    78 TRUE
4 David  23    96 TRUE

Inspecting Data Frames

head(students)     # First 6 rows
   name age grade pass
1 Alice  20    92 TRUE
2   Bob  22    85 TRUE
3 Carol  21    78 TRUE
4 David  23    96 TRUE
nrow(students)     # Number of rows: 4
[1] 4
ncol(students)     # Number of columns: 4
[1] 4
dim(students)      # Dimensions: 4 4
[1] 4 4
str(students)      # Structure overview
'data.frame':   4 obs. of  4 variables:
 $ name : chr  "Alice" "Bob" "Carol" "David"
 $ age  : num  20 22 21 23
 $ grade: num  92 85 78 96
 $ pass : logi  TRUE TRUE TRUE TRUE
summary(students)  # Statistical summary
     name                age            grade         pass        
 Length:4           Min.   :20.00   Min.   :78.00   Mode:logical  
 Class :character   1st Qu.:20.75   1st Qu.:83.25   TRUE:4        
 Mode  :character   Median :21.50   Median :88.50                 
                    Mean   :21.50   Mean   :87.75                 
                    3rd Qu.:22.25   3rd Qu.:93.00                 
                    Max.   :23.00   Max.   :96.00                 

Accessing Data Frame Columns

students <- data.frame(
  name  = c("Alice", "Bob", "Carol"),
  grade = c(92, 85, 78)
)

# Access a column with $
students$name     # "Alice" "Bob" "Carol"
[1] "Alice" "Bob"   "Carol"
students$grade    # 92 85 78
[1] 92 85 78
# Access by position [row, column]
students[1, ]     # First row
   name grade
1 Alice    92
students[, 2]     # Second column
[1] 92 85 78
students[2, 1]    # Row 2, Column 1: "Bob"
[1] "Bob"
# Filter rows
students[students$grade > 80, ]
   name grade
1 Alice    92
2   Bob    85

Your First Plot!

# Simple scatter plot
x <- 1:10
y <- x^2

plot(x, y,
     main  = "My First R Plot",
     xlab  = "X Values",
     ylab  = "Y = X squared",
     col   = "steelblue",
     pch   = 16,      # filled circles
     type  = "b")     # both points and lines

# Bar chart
grades <- c(A = 5, B = 8, C = 4, D = 1)
barplot(grades,
        main = "Grade Distribution",
        col  = c("green", "blue", "orange", "red"))

Getting Help in R

# How to get help
# Use the help() function or the Help panel in RStudio
help("mean")
help("sum")

# Check function arguments
args(round)

# See a function's source code
print

# Useful for packages
vignette("dplyr")

Tip

Google is your friend! Search “R how to [do something]” – Stack Overflow has answers for almost everything.

Common Error Messages

Error What it Means Fix
object 'x' not found Variable doesn’t exist Check spelling / create it first
could not find function Package not loaded Run library(package)
unexpected symbol Syntax error Check for missing commas/parentheses
NAs introduced by coercion Type conversion failed Check your data types
subscript out of bounds Index too large Check length() or nrow()

Exercise 1: Basic Operations

Try these in your RStudio Console:

# 1. Calculate: (15 + 3) * 2 / 4
# 2. Create a variable called "my_name" with your name
# 3. Create a vector of 5 of your favorite numbers
# 4. Find the mean of your vector
# 5. Which numbers in your vector are greater than the mean?

Note

Type the code yourself – don’t copy-paste! Muscle memory matters in programming.

Exercise 2: Write a Function

# Write a function called "bmi_calculator" that:
# - Takes weight (kg) and height (m) as arguments
# - Calculates BMI = weight / height^2
# - Returns the BMI value

# Test it with: weight = 70 kg, height = 1.75 m
# Expected answer: 22.86

# BONUS: Add an if-else inside that prints:
# "Underweight" if BMI < 18.5
# "Normal" if BMI 18.5-24.9
# "Overweight" if BMI >= 25

Exercise 3: Data Frame

# 1. Create a data frame with 5 students:
#    - name, major, year (1-4), gpa (0.0-4.0)

# 2. Display only students with GPA > 3.5

# 3. Calculate the average GPA

# 4. Add a new column "honor_roll" that is TRUE 
#    if GPA >= 3.7, FALSE otherwise

# 5. How many students are on honor roll?

Key Packages to Learn Next

Package Purpose
tidyverse Data wrangling & visualization
ggplot2 Beautiful graphics
dplyr Data manipulation
readr Reading CSV files
tidyr Reshaping data
lubridate Working with dates
stringr Working with text

Quick Reference Card

# -- BASICS ------------------------------------------
x <- 5                    # assign
c(1, 2, 3)                # create vector
1:10                      # sequence
length(x) 
class(x)       # inspect

# -- DATA FRAMES -------------------------------------
df <- data.frame(a=1:3, b=c("x","y","z"))
df$a                      # access column
df[1,]                    # access row
nrow(df); ncol(df)        # dimensions

# -- CONTROL FLOW ------------------------------------
if (x > 0) { } else { }   # conditional
for (i in 1:10) { }       # loop
function(x) { return(x) } # function

# -- USEFUL FUNCTIONS --------------------------------
sum(); mean(); sd(); max(); min()
paste(); paste0()          # combine strings
is.na(); na.omit()         # handle missing

STEP 1: Load package and set directory

library(readxl)
library(dplyr)
library(tidyr)

setwd("C:/Users/Manoj/OneDrive - Kansas State University/00_NRES_research_project")

STEP 2: Read raw data - skip the messy 4-row header

library(readxl)
library(dplyr)
library(tidyr)

setwd("C:/Users/Manoj/OneDrive - Kansas State University/00_NRES_research_project")
yr2020 <- read_excel("01_RawData/CRPPracticesbyCountyJAN20.xlsx", sheet = "JAN20", skip = 4, col_names = FALSE)
yr2021 <- read_excel("01_RawData/CRPPracticesbyCountyJAN21.xlsx", sheet = "JAN21", skip = 4, col_names = FALSE)
yr2022 <- read_excel("01_RawData/CRPPracticesbyCountyJAN22.xlsx", sheet = "JAN22", skip = 4, col_names = FALSE)
yr2023 <- read_excel("01_RawData/CRPPracticesbyCountyJAN23.xlsx", sheet = "JAN23", skip = 4, col_names = FALSE)
yr2024 <- read_excel("01_RawData/CRPPracticesbyCountyJAN24.xlsx", sheet = "JAN24", skip = 4, col_names = FALSE)
yr2025 <- read_excel("01_RawData/CRPPracticesbyCountySEP25.xlsx", sheet = "SEP25", skip = 4, col_names = FALSE)

STEP 3: Check how many columns each year has (USDA adds/removes practices across years)

ncol(yr2020)  # expected: 45 (no CP43, no CP90)
[1] 45
ncol(yr2021)  # expected: 47 (has CP43 and CP90)
[1] 47
ncol(yr2022)  # expected: 47
[1] 47
ncol(yr2023)  # expected: 47
[1] 47
ncol(yr2024)  # expected: 46 (no CP32)
[1] 46
ncol(yr2025)  # expected: 46 (no CP32)
[1] 46

STEP 4: Define column names for each year separately because columns differ across years

  • 2020: has CP32, but NO CP43, NO CP90
col_2020 <- c(
  "fips", "state", "county",
  "cp1", "cp2", "cp3", "cp3a_pine", "cp3a_hardwood",
  "cp4d", "cp4b", "cp5", "cp6_cp7",
  "cp8", "cp9", "cp10", "cp11", "cp12",
  "cp15", "cp16", "cp17", "cp18",
  "cp21", "cp22",
  "cp23", "cp23_floodplain", "cp23a_nonfloodplain",
  "cp24", "cp25",
  "cp27", "cp28", "cp29", "cp30",
  "cp31", "cp32", "cp33", "cp36", "cp37", "cp38",
  "cp39", "cp40", "cp41",
  "cp42",
  "cp87", "cp88",
  "total"
)
  • 2021, 2022, 2023: has CP32, CP43, and CP90
col_2021_2023 <- c(
  "fips", "state", "county",
  "cp1", "cp2", "cp3", "cp3a_pine", "cp3a_hardwood",
  "cp4d", "cp4b", "cp5", "cp6_cp7",
  "cp8", "cp9", "cp10", "cp11", "cp12",
  "cp15", "cp16", "cp17", "cp18",
  "cp21", "cp22",
  "cp23", "cp23_floodplain", "cp23a_nonfloodplain",
  "cp24", "cp25",
  "cp27", "cp28", "cp29", "cp30",
  "cp31", "cp32", "cp33", "cp36", "cp37", "cp38",
  "cp39", "cp40", "cp41",
  "cp42", "cp43",
  "cp87", "cp88", "cp90",
  "total"
)
  • 2024, 2025: NO CP32, but has CP43 and CP90
col_2024_2025 <- c(
  "fips", "state", "county",
  "cp1", "cp2", "cp3", "cp3a_pine", "cp3a_hardwood",
  "cp4d", "cp4b", "cp5", "cp6_cp7",
  "cp8", "cp9", "cp10", "cp11", "cp12",
  "cp15", "cp16", "cp17", "cp18",
  "cp21", "cp22",
  "cp23", "cp23_floodplain", "cp23a_nonfloodplain",
  "cp24", "cp25",
  "cp27", "cp28", "cp29", "cp30",
  "cp31", "cp33", "cp36", "cp37", "cp38",
  "cp39", "cp40", "cp41",
  "cp42", "cp43",
  "cp87", "cp88", "cp90",
  "total"
)

STEP 5 & 6: Pre-process specific years

# Assign column names to each year
colnames(yr2020) <- col_2020
colnames(yr2021) <- col_2021_2023
colnames(yr2022) <- col_2021_2023
colnames(yr2023) <- col_2021_2023
colnames(yr2024) <- col_2024_2025
colnames(yr2025) <- col_2024_2025

# Add a year column to each dataset
yr2020$year <- 2020
yr2021$year <- 2021
yr2022$year <- 2022
yr2023$year <- 2023
yr2024$year <- 2024
yr2025$year <- 2025

STEP 7: Clean junk rows

# Remove junk rows (where fips is not a number)
yr2020 <- yr2020[grepl("^\\d+$", as.character(yr2020$fips)), ]
yr2021 <- yr2021[grepl("^\\d+$", as.character(yr2021$fips)), ]
yr2022 <- yr2022[grepl("^\\d+$", as.character(yr2022$fips)), ]
yr2023 <- yr2023[grepl("^\\d+$", as.character(yr2023$fips)), ]
yr2024 <- yr2024[grepl("^\\d+$", as.character(yr2024$fips)), ]
yr2025 <- yr2025[grepl("^\\d+$", as.character(yr2025$fips)), ]

STEP 8: Stack all datasets

# bind_rows() automatically fills missing columns with NA
crp_all <- bind_rows(yr2020, yr2021, yr2022, yr2023, yr2024, yr2025)

# Quick check
dim(crp_all)      # should show total rows x columns
[1] 14334    48
names(crp_all)    # confirm all column names
 [1] "fips"                "state"               "county"             
 [4] "cp1"                 "cp2"                 "cp3"                
 [7] "cp3a_pine"           "cp3a_hardwood"       "cp4d"               
[10] "cp4b"                "cp5"                 "cp6_cp7"            
[13] "cp8"                 "cp9"                 "cp10"               
[16] "cp11"                "cp12"                "cp15"               
[19] "cp16"                "cp17"                "cp18"               
[22] "cp21"                "cp22"                "cp23"               
[25] "cp23_floodplain"     "cp23a_nonfloodplain" "cp24"               
[28] "cp25"                "cp27"                "cp28"               
[31] "cp29"                "cp30"                "cp31"               
[34] "cp32"                "cp33"                "cp36"               
[37] "cp37"                "cp38"                "cp39"               
[40] "cp40"                "cp41"                "cp42"               
[43] "cp87"                "cp88"                "total"              
[46] "year"                "cp43"                "cp90"               

STEP 9 & 10: Convert and Reshape

# Convert all CP columns to numeric
crp_all <- crp_all %>%
  mutate(across(starts_with("cp"), as.numeric),
         fips = as.integer(fips))

# Reshape from WIDE to LONG format 
# One row per county per practice per year
crp_long <- crp_all %>%
  pivot_longer(
    cols      = starts_with("cp"),   # all CP practice columns
    names_to  = "practice",          # column name -> "practice"
    values_to = "acres"              # column value -> "acres"
  ) %>%
  select(year, fips, state, county, practice, acres)

STEP 11: Add readable practice names

practice_lookup <- data.frame(
  practice = c(
    "cp1", "cp2", "cp3", "cp3a_pine", "cp3a_hardwood",
    "cp4d", "cp4b", "cp5", "cp6_cp7",
    "cp8", "cp9", "cp10", "cp11", "cp12",
    "cp15", "cp16", "cp17", "cp18",
    "cp21", "cp22",
    "cp23", "cp23_floodplain", "cp23a_nonfloodplain",
    "cp24", "cp25",
    "cp27", "cp28", "cp29", "cp30",
    "cp31", "cp32", "cp33", "cp36", "cp37", "cp38",
    "cp39", "cp40", "cp41",
    "cp42", "cp43",
    "cp87", "cp88", "cp90"
  ),
  practice_name = c(
    "Grass Planting - Introduced",
    "Grass Planting - Native",
    "Tree Planting - Softwoods",
    "Tree Planting - Longleaf Pine",
    "Tree Planting - Hardwoods",
    "Wildlife Habitat",
    "Wildlife Corridors",
    "Field Windbreaks",
    "Diversions & Erosion Control",
    "Grass Waterways",
    "Shallow Water for Wildlife",
    "Existing Grass",
    "Existing Trees",
    "Wildlife Food Plots",
    "Contour Grass Strips",
    "Shelterbelts",
    "Living Snow Fences",
    "Salinity Reducing Vegetation",
    "Filter Strips",
    "Riparian Buffers",
    "Wetland Restoration",
    "Wetland Restoration - Floodplain",
    "Wetland Restoration - Non-Floodplain",
    "Cross Wind Trap Strips",
    "Rare and Declining Habitat",
    "Farmable Wetland - Wetland",
    "Marginal Pasture Buffer - Buffer",
    "Marginal Pasture Buffer - Wildlife",
    "Marginal Pasture Buffer - Wetland",
    "Bottomland Hardwood Trees",
    "Expired Hardwood Trees",
    "Upland Bird Habitat Buffers",
    "Longleaf Pine",
    "Duck Nesting Habitat",
    "State Acres for Wildlife Enhancement",
    "Constructed Wetlands",
    "Aquaculture Wetlands",
    "Flooded Prairie Wetlands",
    "Pollinator Habitat",
    "Prairie Strips",
    "CRP Grasslands - Introduced",
    "CRP Grasslands - Native",
    "Soil Health Perennial Conservation Cover"
  )
)

crp_long <- left_join(crp_long, practice_lookup, by = "practice")

STEP 12: Preview final result

head(crp_long)
# A tibble: 6 × 7
   year  fips state   county  practice      acres practice_name                
  <dbl> <int> <chr>   <chr>   <chr>         <dbl> <chr>                        
1  2020  1001 ALABAMA AUTAUGA cp1            NA   Grass Planting - Introduced  
2  2020  1001 ALABAMA AUTAUGA cp2            NA   Grass Planting - Native      
3  2020  1001 ALABAMA AUTAUGA cp3           882.  Tree Planting - Softwoods    
4  2020  1001 ALABAMA AUTAUGA cp3a_pine      79.4 Tree Planting - Longleaf Pine
5  2020  1001 ALABAMA AUTAUGA cp3a_hardwood  39.4 Tree Planting - Hardwoods    
6  2020  1001 ALABAMA AUTAUGA cp4d           10.1 Wildlife Habitat             
dim(crp_long)
[1] 616362      7

Thank You!

Happy Coding! 🎉

Remember: Every expert was once a beginner.
The best way to learn R is to use R every day!