R: R Data Types

Last updated: 2026-08-26

In the previous lesson, we learned about assignment and output. All data in R programs—numbers, text, and booleans—have their own distinct "types." In this lesson, we’ll thoroughly explore R’s six basic data types and master "type conversion," an essential skill for data science in R.

R is a dynamically typed language, but that doesn’t mean types aren’t important—90% of R errors are related to type conversions.

1. What You'll Learn



2. The "Seemingly Equal" Trap

Before writing any code, let’s look at an example that confuses countless beginners:

R
# These two numbers look the same, but R considers them "unequal"
1 == 1L
# [1] FALSE

# Verify their types
typeof(1)
# [1] "double"  (Double-precision floating-point numbers)

typeof(1L)
# [1] "integer" (Integer)

Isn't that counterintuitive? In R, "1" and "1L" are not the same thing. In this lesson, we'll uncover all the secrets of R data types.



3. The 6 Basic Data Types in R

All data in R belongs to one of the following six basic types:

100%
graph TB
    A[R Data Types]
    A --> B[numeric<br/>Double-precision floating-point numbers<br/>Default number]
    A --> C[integer<br/>Integer<br/>Need to add L Suffix]
    A --> D[character<br/>String<br/>Quotation marks must be used]
    A --> E[logical<br/>Logical value<br/>TRUE/FALSE]
    A --> F[complex<br/>Plural<br/>1+2i]
    A --> G[raw<br/>Byte<br/>as.raw 0xff]
    
    style A fill:#fff3cd
    style B fill:#cce5ff
    style C fill:#cce5ff
    style D fill:#d4edda
    style E fill:#f8d7da
    style F fill:#e1d4ff
    style G fill:#ffe1e1

(1) Overview Table of the 6 Types

Type Meaning Example what typeof() returns
numeric Double-precision floating-point number (default) 3.14, -2.5, 1e3 "double"
integer Integer (must be suffixed with L) 1L, 100L, -5L "integer"
character String (must be quoted) "Hello", 'R' "character"
logical Logical value (Boolean) TRUE, FALSE "logical"
complex plural 1+2i, 3-4i "complex"
raw Byte type as.raw(0xff) "raw"
💡 Tip: In actual development, the four most commonly used types are: numeric, character, logical, and integer. Complex and raw are rarely used.

(2) Detailed Explanation of Each Type

R
# numeric —— Double-precision floating-point numbers(Default number)
x <- 3.14
typeof(x)
# [1] "double"

# integer -- Strict Integers (Add L Suffix)
x <- 10L
typeof(x)
# [1] "integer"

# character —— String
x <- "Hello R"
typeof(x)
# [1] "character"

# logical —— Logical value(Must be all uppercase)
x <- TRUE
typeof(x)
# [1] "logical"

# complex —— Plural
x <- 1 + 2i
typeof(x)
# [1] "complex"
⚠️ Note: Logical values must be in all caps: TRUE cannot be written as true or True; doing so will result in a object 'true' not found error.

(3) Integers vs. Floating-Point Numbers: When to Use Which?

Scenario Recommended Type Reason
General mathematical calculations numeric R default; no need to worry about this
Large numerical arrays (1 billion+ elements) integer Saves half the memory
Bitwise operations, IDs, counting integer Semantically unambiguous
Results of floating-point comparisons, sqrt(), etc. numeric Mathematical operations are inherently floating-point
R
# Performance Comparison(1 A billion integers vs 1 A billion floating-point numbers)
# integer: ~400 MB
# numeric: ~800 MB

# Not required in normal situations integer,numeric That's enough
💡 Tip: You don’t need the integer type at all during the beginner stage. Unless you’re performing large-scale computations (1 billion+ elements), numeric is sufficient.



4. typeof() vs class(): Two Functions That Are Easily Confused

R has two functions that can both check for "type," but they have different meanings.

(1) A Quick Visual Guide to the Differences

100%
graph TB
    A["R Object"] --> B["typeof()<br/>Bottom Layer C Type<br/>6 Basic Types"]
    A --> C["class()<br/>Business OOP Class<br/>data.frame / Date / factor"]
    
    B --> D["double / integer<br/>character / logical<br/>complex / raw"]
    C --> E["Business Concepts<br/>(20+ kinds)"]
    
    style A fill:#fff3cd
    style B fill:#cce5ff
    style C fill:#d4edda

(2) Actual Comparison

R
# 1. Ordinary Vectors:The two are consistent
x <- 1:10
typeof(x)
# [1] "integer"
class(x)
# [1] "integer"

# 2. Data Frame: The two are different!
y <- data.frame(a = 1:3, b = c("x", "y", "z"))
typeof(y)
# [1] "list"        ← The bottom layer is list

class(y)
# [1] "data.frame"  ← In business terms, it's a data frame.

(3) Selection Recommendations

Scenario Which one to use
Want to know "what this is inside R" typeof()
Want to know "what this means for the business" class()
Beginners Recommended class() (more intuitive)


5. Type Checking: The is.* Function Family

R provides the is.* function family for type checking, and all functions return TRUE or FALSE.

(1) Common Check Functions

Check Function Purpose Sample Results
is.numeric(x) Is numeric (numeric or integer) is.numeric(1L) → TRUE
is.integer(x) Is a strict integer (with an "L" suffix) is.integer(1) → FALSE
is.character(x) Is string is.character("a") → TRUE
is.logical(x) is a logical value is.logical(TRUE) → TRUE
is.na(x) Is a missing value NA is.na(NA) → TRUE
is.null(x) Is NULL (empty value) is.null(NULL) → TRUE

(2) Key Pitfall: is.numeric() does not distinguish between integers and doubles

R
# is.numeric() is the "superset" of is.integer()
is.numeric(1)     # [1] TRUE
is.numeric(1L)    # [1] TRUE
is.integer(1)     # [1] FALSE
is.integer(1L)    # [1] TRUE
💡 Tip: To check if a value is a number, use is.numeric(); to check if it is a strict integer, use is.integer().



6. Type Conversion: The as.* Function Family

The as.* function family in R can coerce one type into another.

(1) Common Conversion Functions

Conversion Function Purpose Failure Behavior
as.numeric(x) → Number Return NA + Warning
as.integer(x) → Integer Truncate Decimal
as.character(x) → String Always successful
as.logical(x) → Logical value 0 → FALSE, other numbers → TRUE

(2) The Cost of a Failed Conversion

R
# String → Numbers(Success)
as.numeric("3.14")
# [1] 3.14

# String → Numbers(Failure)
as.numeric("Hello")
# Warning: NAs introduced by coercion
# [1] NA
⚠️ Note: When performing a batch conversion, be sure to check the number of NA:

R
# One failure won't stop me,But there will be a warning
as.numeric(c("1", "2", "abc", "4"))
# Warning: NAs introduced by coercion
# [1]  1  2 NA  4

(3) Real-world scenario: Type mismatch after reading a CSV file

One of the most common pitfalls when reading CSV files is that numeric columns are interpreted as characters:

R
# Suppose we read one CSV,All columns are character
df <- data.frame(
  id = c("1", "2", "3"),
  value = c("10.5", "20.3", "30.1")
)

# Before Conversion
str(df)
# 'data.frame':	3 obs. of  2 variables:
#  $ id   : chr  "1" "2" "3"
#  $ value: chr  "10.5" "20.3" "30.1"

# After conversion
df$id <- as.numeric(df$id)
df$value <- as.numeric(df$value)
str(df)
#  $ id   : num  1 2 3
#  $ value: num  10.5 20.3 30.1
💡 Tip: In Lesson 11, when we learn about readr::read_csv(), it will automatically infer the type—it’s much smarter than read.csv(), so this problem won’t occur.



  1. Special Values: NA / NaN / Inf / NULL

R has four special values with completely different meanings—the biggest pitfall for beginners.

(1) The Relationship Among the Four Special Values

100%
graph TB
    A["Missing values/Null value"]
    A --> B[NA<br/>Missing values Not Available<br/>Missing Data,Not assigned,Conversion Failed]
    A --> C[NaN<br/>Non-numeric Not a Number<br/>Not defined mathematically]
    A --> D[Inf<br/>Infinity Infinity<br/>1/0,exp 1000]
    A --> E[NULL<br/>Empty object<br/>Undefined,Functions with no return value]
    
    B --> F[Includes NaN]
    
    style A fill:#fff3cd
    style B fill:#d4edda
    style C fill:#f8d7da
    style D fill:#cce5ff
    style E fill:#e1d4ff

(2) Comparison Table of Four Special Values

Special Value typeof Meaning Usage Scenario Check Function
NA logical Missing value Missing data, unassigned, conversion failed is.na()
Not a Number double non-numeric 0/0,sqrt(-1) is.nan()
Inf double positive infinity 1/0, exp(1000) is.infinite()
NULL NULL empty object undefined, function returns no value is.null()

(3) NA: The most common type of "missing data"

R
# NA Participating in calculations is contagious(NA It won't disappear)
x <- c(1, 2, NA, 4)
sum(x)
# [1] NA  <- The entire result turned out NA

# Must use na.rm = TRUE Skip NA
sum(x, na.rm = TRUE)
# [1] 7

# Inspection NA Location
is.na(x)
# [1] FALSE FALSE  TRUE FALSE

(4) NaN: "Not defined" in mathematics

R
# 0 Divide by 0
0 / 0
# [1] NaN

# Taking the square root of a negative number
sqrt(-1)
# Warning: NaNs produced
# [1] NaN

# NaN It is special. NA(NA a subset of)
is.na(NaN)
# [1] TRUE  ← NaN Me too NA

(5) Info: "Infinity" in mathematics

R
# 1 Divide by 0
1 / 0
# [1] Inf

# A negative number divided by 0
-1 / 0
# [1] -Inf

# Inspection Inf
is.infinite(c(1, Inf, -Inf, 2))
# [1] FALSE  TRUE  TRUE FALSE

(6) NULL: An empty object (or one that does not even exist)

R
# NULL Doesn't take up memory
x <- NULL
length(x)
# [1] 0

# NA occupies 1 position, NULL disappears entirely
length(c(1, 2, NA, 4))    # [1] 4
length(c(1, 2, NULL, 4))  # [1] 3  ← NULL Swallowed whole

# Default return value for functions with no return value NULL
my_void_func <- function() { }
result <- my_void_func()
is.null(result)
# [1] TRUE
⚠️ Note: The fundamental difference between NA and NULL: NA means "the position exists but the value is unknown," while NULL means "the position does not exist at all." The former is often used to indicate missing data, while the latter is often used when a function has no return value.



7. Complete Example: Comprehensive Practice in Type Conversion

Below is an example of a complete workflow that ties together all the concepts covered in this lesson.

▶ Example: Cleaning User-Input Data

R
# ============================================
# Cleaning User-Input Data
# Features:Convert a character vector to a number,Processing NA
# ============================================

# 1. Simulate from CSV Read"Dirty Data"(All of them character)
raw_data <- c("1", "2.5", "3.14", "abc", "5", "", "7.8")
cat("Raw Data:\n")
print(raw_data)
cat("Primitive Types:", typeof(raw_data), "\n\n")

# 2. Convert to a number ("abc" and "" will become NA)
nums <- as.numeric(raw_data)
cat("After conversion:\n")
print(nums)

# 3. See which ones are NA
na_positions <- is.na(nums)
cat("\nNA Location:")
print(na_positions)

# 4. Statistics NA Quantity
na_count <- sum(na_positions)
cat("\nNA Quantity:", na_count, "\n")

# 5. Keep only non- NA the number
clean_nums <- nums[!na_positions]
cat("\nData After Cleaning:")
print(clean_nums)

# 6. Statistical Indicators
cat("\n=== Statistical Indicators ===\n")
cat("Total Number of Elements:", length(raw_data), "\n")
cat("Valid Data:", length(clean_nums), "\n")
cat("Invalid data:", na_count, "\n")
cat("Total:", sum(clean_nums), "\n")
cat("Average:", round(mean(clean_nums), 2), "\n")
cat("Maximum value:", max(clean_nums), "\n")
cat("Minimum value:", min(clean_nums), "\n")
▶ Try it Yourself

Expected Output (Excerpt):

TEXT 📖 Display only
Raw Data:
[1] "1" "2.5" "3.14" "abc" "5" "" "7.8"
Primitive Types: character

After conversion:
[1] 1.00 2.50 3.14   NA 5.00   NA 7.80

NA Location:
[1] FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE

NA Quantity: 2

Data After Cleaning:
[1] 1.00 2.50 3.14 5.00 7.80

=== Statistical Indicators ===
Total Number of Elements: 7
Valid Data: 5
Invalid data: 2
Total: 19.44
Average: 3.89
Maximum value: 7.8
Minimum value: 1

(1) Procedure

Step Action Description
1 Create RStudio Project r-types File → New Project
2 Create a new script data_cleaning.R Copy the code above
3 Select All → Ctrl+Enter Send to Console
4 Observe the output See the "NA" label and the results after cleaning

❓ FAQ

Q Which one should I use, typeof() or class()?
A Use typeof() (6 basic types) if you want to know about R’s internal underlying types; use class() (data.frame/Date/factor) if you want to know about business types. For beginners, class() is more intuitive.
Q Why does is.numeric(1L) return TRUE, but is.integer(1L) also return TRUE?
A Because is.numeric() is the "parent set" of [YIJIAN3PH"—an integer is always a numeric, but the reverse is not true. Recommendation: Use is.numeric() to check if a value is a "number," and use is.integer() to check if it is a "strict integer."
Q What do as.numeric("3.14") and as.numeric("Hello") return?
A The former returns 3.14 (success), while the latter returns NA and prints the warning NAs introduced by coercion. When performing batch conversions, be sure to check the number of is.na() entries; otherwise, all subsequent calculations will return NA.
Q What is NA + 1 equal to?
A It is equal to NA. NA is contagious; the result of any arithmetic operation involving NA is NA. To bypass NA, use the na.rm = TRUE parameter (e.g., sum(x, na.rm = TRUE)).
Q How do I choose between NULL and NA?
A Use NA to indicate "missing data" (the location exists, but the value is unknown); use NULL to indicate "object does not exist" (not even a location exists). NA is used in the vast majority of data processing scenarios.

📖 Summary


📝 Exercises

  1. Basic Exercise: Define 6 variables representing the 6 basic data types (numeric, integer, character, logical, complex, raw). Use typeof() to check the type of each variable, and save screenshots of the output from the 6 typeof() commands.

  2. Basic Problem: Use as.numeric() to convert the character vector c("1", "2.5", "3.14", "abc", "5") into numbers, log the warning messages and the conversion results, and use is.na() to identify which elements have become NA. Take a screenshot of the console output and save it.

  3. Basic Exercise: In the RStudio console, calculate 0/0, 1/0, -1/0, and sqrt(-1), record each result, and use is.na(), is.nan(), and is.infinite() to verify which special value each one belongs to.

  4. Advanced Problem: Define a vector scores <- c(85, 92, NA, 78, NA, 95, 88). Requirements: ① Calculate the total score (excluding NA); ② Calculate the average score (excluding NA, rounded to 2 decimal places); ③ Use !is.na() to filter out elements that are not NA; ④ Count the number of NA values. Save a screenshot of the output for each step.

  5. Challenge: Write an R script to simulate a "type mismatch after reading a CSV file": ① Manually construct a data.frame where all columns are of type character; ② Use as.numeric() to batch-convert one of the columns to numeric; ③ Use sum(is.na(df$col)) to count the number of elements that failed to convert; ④ Use paste() to construct a warning message and output it. After running the script, take a screenshot and save the entire console output.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏