Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

R (4.6)  Module 2 – Vectors, types and missing values

Atomic vectors, types and coercion

R's six atomic types, typeof(), class() and mode(), what c() does to mixed values, converting with as.numeric() without silent NAs, and names on vectors.

  • Beginner
  • 10 minutes
  • Examples run with R 4.6.1 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 10 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Name the six atomic types and tell typeof(), class() and mode() apart
  • Predict the type c() gives a vector that mixes values of different types
  • Convert between types with as.*() and find the NAs a conversion introduced
  • Add, change and remove the names of a vector's elements

Before you start

What you’ll learn · Before you start

What you will learn

  • Name the six atomic types and tell typeof(), class() and mode() apart
  • Predict the type c() gives a vector that mixes values of different types
  • Convert between types with as.*() and find the NAs a conversion introduced
  • Add, change and remove the names of a vector's elements

Before you start

On this page

c(12, 7.5, "N/A") looks like three amounts, but R stores it as three pieces of text, "12", "7.5" and "N/A", and sum() of it stops with an error. One value of another type changed all three, because an R vector holds values of a single type, and R chooses that type by a few strict rules.

The runs on this page show those rules at work in R 4.6.1. You will name R’s six atomic types and tell typeof(), class() and mode() apart, predict the type c() gives mixed values, convert text to numbers on purpose while catching every value that turns into NA, and label the elements of a vector with names.

Even one number is a vector, and a vector has one type

Type 42 at the console and R answers [1] 42. The [1] is the position of the first value on that line, because even a single number is a vector, of length 1. A vector is a row of values of one type, and R has six such types. The R Language Definition calls them the basic, or atomic, vector types, so a vector made of them is an atomic vector: A vector whose elements all have one of R's six basic types: logical, integer, double, complex, character or raw. A single value such as 42 is an atomic vector of length 1.. Here is each type with the way you type a value of it and what class() reports:

typeof() Typed as class()
"logical" TRUE, FALSE "logical"
"integer" 7L, 1:3 "integer"
"double" 7, 2.5, 1e6 "numeric"
"complex" 2+3i "complex"
"character" "seven" "character"
"raw" as.raw(255) "raw"

Logical vectors hold TRUE, FALSE and NA. Integers are whole numbers stored exactly in 32 bits, up to 2,147,483,647 either way. Doubles are real numbers in binary floating point with 53 bits of precision, about 15 significant digits, and they are what R makes of any number you type without an L. Character vectors hold text. Complex numbers and raw bytes exist for special work and rarely appear in an analysis.

The run below asks R about each type, and then asks the same values three different questions:

types.R, typed at the R console Python · types_session.py
from session import run, version

version()
# R reads types.R as if each line were typed at the console.
run("""
R --vanilla --quiet -f types.R
""")

Output

# R version 4.6.1 -- "Happy Hop"
$ R --vanilla --quiet -f types.R
> # One number is a vector of length 1.
> x <- 42
> length(x)
[1] 1
> # typeof() names the type R stores the values in.
> typeof(7)
[1] "double"
> typeof(7L)
[1] "integer"
> typeof(TRUE)
[1] "logical"
> typeof("seven")
[1] "character"
> typeof(2+3i)
[1] "complex"
> typeof(as.raw(255))
[1] "raw"
> # mode() calls both integer and double "numeric".
> mode(7L)
[1] "numeric"
> mode(7)
[1] "numeric"
> # class() is what functions look at to decide what to do.
> class(7)
[1] "numeric"
> class(1:3)
[1] "integer"
> class(matrix(1:4, nrow = 2))
[1] "matrix" "array" 
> # A whole number typed without L is still a double.
> is.integer(7)
[1] FALSE
> is.integer(7L)
[1] TRUE

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 types_session.py

The three functions answer different questions:

  • typeof() names how the values are stored: "double" for 7, "integer" for 7L.
  • mode() is an older, coarser grouping kept from the S language, which calls both integers and doubles "numeric".
  • class() is what functions such as print() and summary() look at to decide how to treat an object. A plain vector has an implicit class, "numeric" for a double, and a matrix of the same numbers is c("matrix", "array").

Use typeof() when storage matters (a whole number that overflows, a column read as text), class() when you want to know how functions will treat an object, and mode() rarely.

Expecting 7 to be an integer

typeof(7) is "double" and is.integer(7) is FALSE, as the run shows. A whole number you type is an integer only when you write it with an L, as in 7L; 1:3 and as.integer() make integers too. is.integer() tests the storage, not whether the value happens to be whole.

Checkpoint

Check: The six atomic types

  1. Question 1 of 2 What does typeof(7) return?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: "double"

    typeof() names how the values are stored. 7 is a double; 7L is an integer. class(7) and mode(7) both say "numeric", which is why the three functions are easy to confuse.

  2. Question 2 of 2 x <- 5 and y <- 5L. Which call gives a different answer for x and for y?

    Choose one answer.

    A hint

    Two of the functions group integers and doubles together.

    Show the answer: Question 2 of 2

    Answer: typeof()

    Only typeof() separates them: "double" for 5 and "integer" for 5L. mode() says "numeric" for both, and is.numeric() is TRUE for both. (class() would differ too, "numeric" against "integer".)

c() gives mixed values the most flexible type

c(1, TRUE, FALSE) returns 1 1 0, numbers, and c(1, "a", TRUE) returns "1" "a" "TRUE", text. A vector cannot hold a number beside a piece of text, so coercion: Converting values from one type to another. c() does it by itself when it combines values of different types; as.numeric(), as.character() and the other as.*() functions do it on request. converts every value to one type. The help page of c() gives the order R picks from:

  • logical < integer < double < complex < character

The result takes the highest type among its values. A type higher up can hold every value of the types below it, written its own way: TRUE is 1 as a number and "TRUE" as text, and a number becomes its digits written as text. Raw sits below logical in the same order, and the lists of a later lesson sit above character.

Step through a vector that gains one value at a time, v <- c(v, value), and watch it climb:

Interactive · step by step How c() climbs the ladder of types Step through the vector v of the coercion example as it gains one value at a time. The dashed arrow points at the type it has now.
How c() climbs the ladder of types, step 6 of 6. Showing character, complex, double, integer, logical, v ("TRUE" "1" "2.5" "a"). In focus: character.charactertext such as "a"complexsuch as 1+2idoublesuch as 2.5integersuch as 1LlogicalTRUE, FALSEv"TRUE" "1" "2.5" "a"

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. The ladder of types. The help page of c() orders the atomic types from least to most flexible. A type higher up can hold every value of the types below it, written its own way.
  2. v <- TRUE. v starts as one logical value, on the lowest rung.
  3. v <- c(v, 1L). 1L is an integer, so the whole vector moves up to integer. TRUE becomes 1, the number it stands for in arithmetic, and v prints as 1 1.
  4. v <- c(v, 2.5). 2.5 is a double, so v moves up again. The values stay 1 and 1; only the way they are stored changes, and v prints as 1.0 1.0 2.5.
  5. v <- c(v, "a"). Text sits on the top rung. Every number is written out as text, so the first value, once TRUE, is now the string "1".
  6. All at once. c(TRUE, 1L, 2.5, "a") converts each value straight to text, so TRUE becomes "TRUE". A conversion that has happened is never undone, so the order of the steps decided the first value.

The first value of v ended as "1", while the same values combined in one call give "TRUE". Each step converts the values it has, and a conversion is never undone. Here are those lines, with the opening’s amounts and a few more mixtures, typed at the console:

coercion.R, typed at the R console Python · coercion_session.py
from session import run, version

version()
# R reads coercion.R as if each line were typed at the console.
run("""
R --vanilla --quiet -f coercion.R
""")

Output

# R version 4.6.1 -- "Happy Hop"
$ R --vanilla --quiet -f coercion.R
> # Three amounts, one of them typed as text.
> amounts <- c(12, 7.5, "N/A")
> amounts
[1] "12"  "7.5" "N/A"
> try(sum(amounts))
Error in sum(amounts) : invalid 'type' (character) of argument
> # c() gives every value the most flexible type among them.
> c(1, TRUE, FALSE)
[1] 1 1 0
> c(1L, 2.5)
[1] 1.0 2.5
> c(2.5, 1+2i)
[1] 2.5+0i 1.0+2i
> c(1, "a", TRUE)
[1] "1"    "a"    "TRUE"
> # One value at a time, the vector climbs the ladder.
> v <- TRUE
> v <- c(v, 1L)
> v
[1] 1 1
> v <- c(v, 2.5)
> v
[1] 1.0 1.0 2.5
> v <- c(v, "a")
> v
[1] "1"   "1"   "2.5" "a"  
> # Once v is text, mean() has no numbers to average.
> mean(v)
[1] NA
Warning message:
In mean.default(v) : argument is not numeric or logical: returning NA
> # All at once, TRUE goes straight to text.
> c(TRUE, 1L, 2.5, "a")
[1] "TRUE" "1"    "2.5"  "a"   
> # NA takes the type of the vector it joins.
> typeof(c(1.5, NA))
[1] "double"
> typeof(c("a", NA))
[1] "character"

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 coercion_session.py

Marking a missing number with text

A loop that collects results with v <- c(v, value) and stores "missing" for a failed value turns every number in v into text, and mean(v) then returns NA with a warning, as it did for the v of the run. Store NA for a missing number, so the vector stays a double.

NA, the missing value, takes the type of the vector it joins: in c(1.5, NA) it is a missing double, in c("a", NA) a missing piece of text. So one gap never changes a vector’s type, while one piece of text does.

Key idea

A vector has one type: c() converts every value to the most flexible type among them, in the order logical, integer, double, complex, character, and a conversion that has happened is never undone.

Checkpoint

Check: How c() picks one type

  1. Question 1 of 2 What does this line return?

    Read the code, then choose one answer.

    c(2, TRUE, "no")
    Show the answer: Question 1 of 2

    Answer: "2" "TRUE" "no"

    The highest type among 2 (double), TRUE (logical) and "no" (character) is character, so all three are written as text: "2", "TRUE" and "no".

  2. Question 2 of 2 What is v after these lines?

    Read the code, then choose one answer.

    v <- c(TRUE, 5L)
    v <- c(v, "x")
    A hint

    Work out v after the first line before you add the text.

    Show the answer: Question 2 of 2

    Answer: "1" "5" "x"

    c(TRUE, 5L) is the integer vector 1 5. Adding "x" makes the vector character, and each number is written as R prints it: "1", "5", "x". The conversion of TRUE to 1 is never undone.

The as.*() functions convert on purpose, and NA marks what failed

as.numeric(" 42 ") is 42, while as.numeric("1,234") is NA with the warning “NAs introduced by coercion”. The functions as.logical(), as.integer(), as.numeric(), as.character() and as.complex() convert a vector to one type when you ask, and their help pages give the rules:

  • Text to numbers reads optional spaces, then a decimal or hexadecimal number, or one of the words Inf and NaN in any case: " 42 " gives 42, "0x1A" 26 and "1e3" 1000. Anything else, a comma included, becomes NA with a warning, and an empty string becomes NA with no warning at all.
  • as.integer() drops the fraction towards zero: 3.7 gives 3, and -3.7 gives -3.
  • as.logical() reads "TRUE", "true", "True" and "T" as TRUE, the four matching spellings as FALSE, and everything else, "yes" and "1" included, as NA. For numbers, 0 is FALSE and every other number TRUE.
  • as.character() writes a number with up to 15 significant digits, in e-notation when that is shorter, so 1/3 becomes "0.333333333333333" and 100000 becomes "1e+05". paste0() does the same, which can turn an identifier such as id_100000 into id_1e+05.

The run tries each rule, then finds which entries a conversion turned into NA:

convert.R, typed at the R console Python · convert_session.py
from session import run, version

version()
# R reads convert.R as if each line were typed at the console.
run("""
R --vanilla --quiet -f convert.R
""")

Output

# R version 4.6.1 -- "Happy Hop"
$ R --vanilla --quiet -f convert.R
> # as.integer() drops the fraction, towards zero.
> as.integer("3.7")
[1] 3
> as.integer(-3.7)
[1] -3
> # as.numeric() trims spaces and reads hex and exponents.
> as.numeric("  42  ")
[1] 42
> as.numeric("0x1A")
[1] 26
> as.numeric("1e3")
[1] 1000
> # It also reads the words Inf and NaN, in any case.
> as.numeric(c("Inf", "-inf", "NaN"))
[1]  Inf -Inf  NaN
> # Text it cannot read becomes NA, with a warning.
> as.numeric("1,234")
[1] NA
Warning message:
NAs introduced by coercion 
> # An empty string becomes NA without any warning.
> as.numeric("")
[1] NA
> # as.logical() knows four spellings of each value.
> as.logical(c("TRUE", "true", "T", "yes", "1"))
[1] TRUE TRUE TRUE   NA   NA
> as.logical(0:2)
[1] FALSE  TRUE  TRUE
> # as.character() and paste() write up to 15 digits,
> # or e-notation when that is shorter.
> as.character(1/3)
[1] "0.333333333333333"
> paste0("id_", 100000)
[1] "id_1e+05"
> format(100000, scientific = FALSE)
[1] "100000"
> # Which entries did the conversion turn into NA?
> raw <- c("12", "7.5", "seven", NA, "")
> num <- suppressWarnings(as.numeric(raw))
> num
[1] 12.0  7.5   NA   NA   NA
> raw[is.na(num) & !is.na(raw)]
[1] "seven" ""     

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 convert_session.py

The warning says that something failed, not what. The last line answers that: an entry that is NA after the conversion but was not NA before is one that failed, here "seven" and the empty string. Keep that line for every conversion of typed data, because the blank never warned. These are the results from the run that surprise people most:

Call Result Warning
as.numeric("1,234") NA yes
as.numeric("") NA none
as.integer(-3.7) -3 none
as.logical("yes") NA none
paste0("id_", 100000) "id_1e+05" none

Before you convert typed amounts, remove what is not part of the number, and remove it precisely. A pattern that keeps only digits and dots also keeps the dot of an abbreviation and throws away a minus sign:

clean_amounts.R, typed at the R console Python · clean_amounts_session.py
from session import run, version

version()
# R reads clean_amounts.R as if each line were typed at the console.
run("""
R --vanilla --quiet -f clean_amounts.R
""")

Output

# R version 4.6.1 -- "Happy Hop"
$ R --vanilla --quiet -f clean_amounts.R
> amounts <- c("₹1,25,000", "3,450.50", "N/A", "Rs. 450", "-1,000")
> # Keeping only digits and dots looks safe. It is not.
> as.numeric(gsub("[^0-9.]", "", amounts))
[1] 125000.00   3450.50        NA      0.45   1000.00
> # Remove the currency first, then the commas, then convert.
> no_currency <- sub("^(Rs\\.?|₹)\\s*", "", amounts)
> cleaned <- gsub(",", "", no_currency)
> cleaned
[1] "125000"  "3450.50" "N/A"     "450"     "-1000"  
> values <- suppressWarnings(as.numeric(cleaned))
> values
[1] 125000.0   3450.5       NA    450.0  -1000.0
> # What could not be read is reported, not hidden.
> amounts[is.na(values)]
[1] "N/A"

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 clean_amounts_session.py

Amounts typed with ₹, Rs. and lakh groupings

Indian amounts are grouped in twos after the last three digits, so "₹1,25,000" is one lakh twenty-five thousand, 125,000. Removing every comma handles both groupings. The trap is "Rs. 450": keeping only digits and dots leaves ".450", which R reads as 0.45, with no warning, and "-1,000" loses its minus sign. Removing the currency at the start first, with sub("^(Rs\\.?|₹)\\s*", "", x), and then the commas gives 450 and -1000.

Number Extractor Paste a block of text and see every number in it, to compare with what as.numeric() reads.

Checkpoint

Check: Converting with as.*()

  1. Question 1 of 2 What does as.integer(-2.9) return?

    Type a number.

    A hint

    as.integer() does not round.

    Show the answer: Question 1 of 2

    Answer: -2

    as.integer() drops the fraction towards zero, as trunc() does, so -2.9 becomes -2. round(-2.9) would give -3.

  2. Question 2 of 2 Which conversion gives NA without any warning?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: as.numeric("")

    Only the empty string turns into NA without a warning. That is why the lesson finds failed conversions by comparing is.na() before and after, instead of trusting the warning.

Names label the elements of a vector

c(Mon = 31.5, Tue = 33.0, Wed = 29.8) prints each value under its day. The names are not part of the values: they are an attribute: Extra information R stores beside a vector's values, such as its names, its dimensions or its class. attributes(x) lists them., extra information R stores beside a vector, which attributes() lists and str() reports as a Named num. Step through what each call does to them:

Interactive · step by step Names are an attribute beside the values Step through the names example. The values and the names are stored apart; watch which steps change the names and which leave them alone.
Names are an attribute beside the values, step 4 of 4. Showing temps, values. In focus: values.tempsvalues31.5 33.0 29.8

The drawing shows the whole scene; its 4 steps are listed below.

Every step as text
  1. c(Mon = 31.5, ...). Writing name = value pairs inside c() makes one vector of three doubles and stores the three names beside it. str() calls it a Named num.
  2. names(temps). names() reads the attribute and returns it as a character vector of the same length as the values.
  3. names(temps)[2] <- "Tues". Assigning to one position of names() changes that name alone. The values are untouched.
  4. unname(temps). unname(temps) returns the values without the attribute, as drawn here, and as.numeric() does the same, because it drops every attribute. temps itself keeps its names until you assign the result.

The same calls, and two more, typed at the console:

names.R, typed at the R console Python · names_session.py
from session import run, version

version()
# R reads names.R as if each line were typed at the console.
run("""
R --vanilla --quiet -f names.R
""")

Output

# R version 4.6.1 -- "Happy Hop"
$ R --vanilla --quiet -f names.R
> # Names can be given as the vector is made.
> temps <- c(Mon = 31.5, Tue = 33.0, Wed = 29.8)
> temps
 Mon  Tue  Wed 
31.5 33.0 29.8 
> names(temps)
[1] "Mon" "Tue" "Wed"
> str(temps)
 Named num [1:3] 31.5 33 29.8
 - attr(*, "names")= chr [1:3] "Mon" "Tue" "Wed"
> # Arithmetic keeps the names.
> temps * 9 / 5 + 32
  Mon   Tue   Wed 
88.70 91.40 85.64 
> # One name can be changed in place.
> names(temps)[2] <- "Tues"
> temps
 Mon Tues  Wed 
31.5 33.0 29.8 
> # Too few names: the rest become NA.
> rain <- c(12, 0, 7)
> names(rain) <- c("Mon", "Tue")
> rain
 Mon  Tue <NA> 
  12    0    7 
> # unname() and as.numeric() return the values alone.
> unname(temps)
[1] 31.5 33.0 29.8
> as.numeric(temps)
[1] 31.5 33.0 29.8

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 names_session.py

The run shows four rules:

  • names(x) <- value sets them, and names(x)[2] <- "Tues" changes one. names(x) reads them back as a character vector.
  • Too few names are filled with NA. Two names for three rainfall values leave the third named <NA>.
  • Arithmetic keeps the names. temps * 9 / 5 + 32 gives Fahrenheit values still labelled Mon, Tue and Wed.
  • unname() and as.numeric() drop them, because as.numeric(), like the other as.*() conversions of this page, strips every attribute.

Names make results readable and let you pick values by label, as in temps["Wed"], which the lesson on indexing covers.

Checkpoint

Check: Names on a vector

  1. Question 1 of 2 x <- 1:4, then names(x) <- c("a", "b"). What does names(x) return?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: "a" "b" NA NA

    The help page of names() says a shorter value is extended by character NAs, so the last two elements are named NA. They print as <NA>.

  2. Question 2 of 2 Which of these lines returns a vector that still has the names a and b?

    Read the code, then choose one answer.

    p <- c(a = 1.5, b = 2)
    Show the answer: Question 2 of 2

    Answer: p * 10

    Names are an attribute. Arithmetic copies it to the result; unname() and conversions such as as.numeric() remove it.

Practise: predict, then check

Each line below mixes the ideas of this page. Before you look at the run, write down what you expect each line to print, with its type.

Predict first

For x <- c(score = 7, total = "10"), predict typeof(x), x, as.numeric(x) and c(x, extra = TRUE), then as.integer(c("4.9", "-4.9", "four")) and as.logical(c("False", "no", "0")). Then type them in your own R and compare with the run.

practice.R, typed at the R console Python · practice_session.py
from session import run, version

version()
# R reads practice.R as if each line were typed at the console.
run("""
R --vanilla --quiet -f practice.R
""")

Output

# R version 4.6.1 -- "Happy Hop"
$ R --vanilla --quiet -f practice.R
> x <- c(score = 7, total = "10")
> typeof(x)
[1] "character"
> x
score total 
  "7"  "10" 
> as.numeric(x)
[1]  7 10
> c(x, extra = TRUE)
 score  total  extra 
   "7"   "10" "TRUE" 
> as.integer(c("4.9", "-4.9", "four"))
[1]  4 -4 NA
Warning message:
NAs introduced by coercion 
> as.logical(c("False", "no", "0"))
[1] FALSE    NA    NA

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 practice_session.py

The text "10" made the whole vector character, names included; as.numeric() read both values back and dropped the names; TRUE arrived as "TRUE"; as.integer() truncated towards zero and failed on "four"; and of the three spellings only "False" is one as.logical() knows.

Then check yourself on types, coercion, conversion and names. Each question explains its answer as soon as you choose, and the next one goes to whichever idea needs more practice:

Practice that adapts to you

Practise this lesson

11 questions about 4 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 11 Which of these is not one of R's six atomic types?

    Choose one answer.

    Show the answer: Question 1 of 11

    Answer: numeric

    The six atomic types are logical, integer, double, complex, character and raw. "numeric" is what mode() and class() call integers and doubles.

  2. Question 2 of 11 What does this print?

    Read the code, then choose one answer.

    x <- 2.5
    c(typeof(x), class(x), mode(x))
    Show the answer: Question 2 of 11

    Answer: "double" "numeric" "numeric"

    For 2.5, typeof() is "double", class() is the implicit class "numeric", and mode() is "numeric".

  3. Question 3 of 11 A function refuses its input unless is.integer(x) is TRUE. Called with counts <- c(3, 4, 5), it refuses. Which call works, without changing the function?

    Choose one answer.

    Show the answer: Question 3 of 11

    Answer: Calling it with as.integer(counts), or with c(3L, 4L, 5L)

    is.integer() asks how the values are stored. c(3, 4, 5) is a double vector; as.integer() or the L suffix makes an integer vector with the same values.

  4. Question 4 of 11 Put these types in the order c() uses, from least to most flexible.

    Give each item its position, from 1 (first).

    Show the answer: Question 4 of 11

    Answer:

    1. logical
    2. integer
    3. double
    4. complex
    5. character

    The help page of c() gives logical < integer < double < complex < character (with raw below logical and list above character). A vector takes the highest type among its values.

  5. Question 5 of 11 What does this return?

    Read the code, then choose one answer.

    sum(c(2, TRUE, TRUE))
    Show the answer: Question 5 of 11

    Answer: 4

    c(2, TRUE, TRUE) is the double vector 2 1 1, because logical values become 1 and 0 when a vector moves up to a number type. Its sum is 4.

  6. Question 6 of 11 What is flags after these three lines?

    Read the code, then choose one answer.

    flags <- c(TRUE, FALSE)
    flags <- c(flags, 0L)
    flags <- c(flags, "no")
    Show the answer: Question 6 of 11

    Answer: "1" "0" "0" "no"

    Each line converts what it has. After the second line flags is the integer vector 1 0 0, and the third line writes each number as text: "1", "0", "0", then "no".

  7. Question 7 of 11 What does as.logical("yes") return?

    Choose one answer.

    Show the answer: Question 7 of 11

    Answer: NA

    The help page of logical lists "T", "TRUE", "True" and "true" as true and the four matching spellings as false; all other text, "yes" and "1" included, becomes NA.

  8. Question 8 of 11 What does paste0("file_", 300000, ".csv") return?

    Choose one answer.

    Show the answer: Question 8 of 11

    Answer: "file_3e+05.csv"

    paste0() converts 300000 with as.character(), which picks e-notation, 3e+05, because it is shorter. For identifiers and file names, convert the number yourself with format(x, scientific = FALSE) or sprintf().

  9. Question 9 of 11 x <- c("1,200", "950", "N/A", ""). How many NA values does as.numeric(gsub(",", "", x)) hold?

    Type a number.

    A hint

    Remove the commas first, then read each value; remember the blank.

    Show the answer: Question 9 of 11

    Answer: 2 values

    gsub() removes the comma, so "1,200" becomes 1200 and "950" stays 950. "N/A" cannot be read and becomes NA with a warning, and the empty string becomes NA with no warning: 2 NA values, but only one of them announced.

  10. Question 10 of 11 Which function returns the values of a named vector without their names?

    Choose one answer.

    Show the answer: Question 10 of 11

    Answer: unname()

    unname(x) gives the values alone. as.numeric(x) also drops names, because it removes every attribute.

  11. Question 11 of 11 What does this print?

    Read the code, then choose one answer.

    p <- c(a = 1.5, b = 2)
    as.integer(p)
    Show the answer: Question 11 of 11

    Answer: [1] 1 2

    as.integer() converts to integer by dropping fractions towards zero, and it strips attributes, so the result is the plain integer vector 1 2.

Interview questions

Warm-up: what do typeof(), class() and mode() each tell you about an R value?

typeof() names the type R stores the values in: for an atomic vector one of "logical", "integer", "double", "complex", "character" or "raw", and other types such as "list" or "closure" for other objects. class() names what functions use to decide how to treat an object: its class attribute if it has one, such as "factor" or "data.frame", otherwise an implicit class, "numeric" for a double and c("matrix", "array") for a matrix. mode(), kept from the S language, reports integers and doubles alike as "numeric". So typeof(7) is "double" while class(7) and mode(7) are both "numeric". Check typeof() when storage matters, such as a column read as text or a whole number that must be an integer, and class() when you need to know what print() or summary() will do.

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    A file of 50,000 payments loads with its amount column as text, and as.numeric() on it gives 312 NA values and a single warning. How do you work out what went wrong, convert the column safely, and show that no amount was changed without anyone noticing?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Fresher to mid

    A loop collects 200 measurements with v <- c(v, value) and stores the word "failed" whenever a measurement fails. At the end mean(v) returns NA with a warning. Explain what happened to the values that were collected before the first failure, and how you would collect the results instead.

    Model answer, Pro. First step and follow-ups

Key takeaways

  • Even a single number is a vector in R, of length 1, and an atomic vector holds values of one of six types: logical, integer, double, complex, character or raw.
  • typeof() reports the storage type, class() what functions dispatch on, and mode() an older grouping that calls integers and doubles "numeric"; a number typed without L is a double.
  • c() converts mixed values to the most flexible type, in the order logical, integer, double, complex, character, and a conversion that has happened is never undone.
  • as.numeric() and its relatives convert on purpose and give NA for what they cannot read, with a warning except for empty strings, so compare is.na() before and after a conversion to find what failed.
  • Names are an attribute: names() reads and sets them, arithmetic keeps them, and unname() and conversions such as as.numeric() drop them.

Terms in this lesson

atomic vector
A vector whose elements all have one of R's six basic types: logical, integer, double, complex, character or raw. A single value such as 42 is an atomic vector of length 1.
attribute
Extra information R stores beside a vector's values, such as its names, its dimensions or its class. attributes(x) lists them.
coercion
Converting values from one type to another. c() does it by itself when it combines values of different types; as.numeric(), as.character() and the other as.*() functions do it on request.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.