library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
typeof(letters)
## [1] "character"
#> [1] "character"
typeof(1:10)
## [1] "integer"
#> [1] "integer"
x <- list("a", "b", 1:10)
length(x)
## [1] 3
#> [1] 3
1:10 %% 3 == 0
## [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
#> [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
c(TRUE, TRUE, FALSE, NA)
## [1] TRUE TRUE FALSE NA
#> [1] TRUE TRUE FALSE NA
typeof(1)
## [1] "double"
#> [1] "double"
typeof(1L)
## [1] "integer"
#> [1] "integer"
1.5L
## [1] 1.5
#> [1] 1.5
x <- sqrt(2) ^ 2
x
## [1] 2
#> [1] 2
x - 2
## [1] 4.440892e-16
#> [1] 4.440892e-16
c(-1, 0, 1) / 0
## [1] -Inf NaN Inf
#> [1] -Inf NaN Inf
x <- "This is a reasonably long string."
pryr::object_size(x)
## 152 B
#> 152 B
y <- rep(x, 1000)
pryr::object_size(y)
## 8.14 kB
#> 8.14 kB
NA # logical
## [1] NA
#> [1] NA
NA_integer_ # integer
## [1] NA
#> [1] NA
NA_real_ # double
## [1] NA
#> [1] NA
NA_character_ # character
## [1] NA
#> [1] NA
x <- c(0, NA, NaN, Inf, -Inf)
is.finite(x)
## [1] TRUE FALSE FALSE FALSE FALSE
#> [1] TRUE FALSE FALSE FALSE FALSE
!is.infinite(x)
## [1] TRUE TRUE TRUE FALSE FALSE
#> [1] TRUE TRUE TRUE FALSE FALSE
The is.finite() function considers non-missing numeric values to be finite, and missing (NA), not a number (NaN), and positive (Inf) and negative infinity (-Inf) to not be finite. The is.infinite() behaves slightly differently. It considers Inf and -Inf to be infinite, and everything else, including non-missing numbers, NA, and NaN to not be infinite
dplyr::near
## function (x, y, tol = .Machine$double.eps^0.5)
## {
## abs(x - y) < tol
## }
## <bytecode: 0x7fdb17fe3b68>
## <environment: namespace:dplyr>
#> function (x, y, tol = .Machine$double.eps^0.5)
#> {
#> abs(x - y) < tol
#> }
#> <bytecode: 0x5d8e8a8>
#> <environment: namespace:dplyr>
Instead of checking for exact equality, it checks that two numbers are within a certain tolerance, tol. By default the tolerance is set to the square root of .Machine$double.eps, which is the smallest floating point number that the computer can represent.
A logical vector can take 3 possible values. How many possible values can an integer vector take? How many possible values can a double take? Use google to do some research.
Brainstorm at least four functions that allow you to convert a double to an integer. How do they differ? Be precise.
function(x, method) {
if (method == "round down") {
floor(x)
} else if (method == "round up") {
ceiling(x)
} else if (method == "round towards zero") {
trunc(x)
} else if (method == "round away from zero") {
sign(x) * ceiling(abs(x))
} else if (method == "nearest, round half up") {
floor(x + 0.5)
} else if (method == "nearest, round half down") {
ceiling(x - 0.5)
} else if (method == "nearest, round half towards zero") {
sign(x) * ceiling(abs(x) - 0.5)
} else if (method == "nearest, round half away from zero") {
sign(x) * floor(abs(x) + 0.5)
} else if (method == "nearest, round half to even") {
round(x, digits = 0)
} else if (method == "nearest, round half to odd") {
case_when(
# smaller integer is odd - round half down
floor(x) %% 2 ~ ceiling(x - 0.5),
# otherwise, round half up
TRUE ~ floor(x + 0.5)
)
} else if (method == "nearest, round half randomly") {
round_half_up <- sample(c(TRUE, FALSE), length(x), replace = TRUE)
y <- x
y[round_half_up] <- ceiling(x[round_half_up] - 0.5)
y[!round_half_up] <- floor(x[!round_half_up] + 0.5)
y
}
}
## function(x, method) {
## if (method == "round down") {
## floor(x)
## } else if (method == "round up") {
## ceiling(x)
## } else if (method == "round towards zero") {
## trunc(x)
## } else if (method == "round away from zero") {
## sign(x) * ceiling(abs(x))
## } else if (method == "nearest, round half up") {
## floor(x + 0.5)
## } else if (method == "nearest, round half down") {
## ceiling(x - 0.5)
## } else if (method == "nearest, round half towards zero") {
## sign(x) * ceiling(abs(x) - 0.5)
## } else if (method == "nearest, round half away from zero") {
## sign(x) * floor(abs(x) + 0.5)
## } else if (method == "nearest, round half to even") {
## round(x, digits = 0)
## } else if (method == "nearest, round half to odd") {
## case_when(
## # smaller integer is odd - round half down
## floor(x) %% 2 ~ ceiling(x - 0.5),
## # otherwise, round half up
## TRUE ~ floor(x + 0.5)
## )
## } else if (method == "nearest, round half randomly") {
## round_half_up <- sample(c(TRUE, FALSE), length(x), replace = TRUE)
## y <- x
## y[round_half_up] <- ceiling(x[round_half_up] - 0.5)
## y[!round_half_up] <- floor(x[!round_half_up] + 0.5)
## y
## }
## }
#> function(x, method) {
#> if (method == "round down") {
#> floor(x)
#> } else if (method == "round up") {
#> ceiling(x)
#> } else if (method == "round towards zero") {
#> trunc(x)
#> } else if (method == "round away from zero") {
#> sign(x) * ceiling(abs(x))
#> } else if (method == "nearest, round half up") {
#> floor(x + 0.5)
#> } else if (method == "nearest, round half down") {
#> ceiling(x - 0.5)
#> } else if (method == "nearest, round half towards zero") {
#> sign(x) * ceiling(abs(x) - 0.5)
#> } else if (method == "nearest, round half away from zero") {
#> sign(x) * floor(abs(x) + 0.5)
#> } else if (method == "nearest, round half to even") {
#> round(x, digits = 0)
#> } else if (method == "nearest, round half to odd") {
#> case_when(
#> # smaller integer is odd - round half down
#> floor(x) %% 2 ~ ceiling(x - 0.5),
#> # otherwise, round half up
#> TRUE ~ floor(x + 0.5)
#> )
#> } else if (method == "nearest, round half randomly") {
#> round_half_up <- sample(c(TRUE, FALSE), length(x), replace = TRUE)
#> y <- x
#> y[round_half_up] <- ceiling(x[round_half_up] - 0.5)
#> y[!round_half_up] <- floor(x[!round_half_up] + 0.5)
#> y
#> }
#> }
#> <environment: 0x2b114b8>
tibble(
x = c(1.8, 1.5, 1.2, 0.8, 0.5, 0.2,
-0.2, -0.5, -0.8, -1.2, -1.5, -1.8),
`Round down` = floor(x),
`Round up` = ceiling(x),
`Round towards zero` = trunc(x),
`Nearest, round half to even` = round(x)
)
## # A tibble: 12 × 5
## x `Round down` `Round up` `Round towards zero` Nearest, round half to e…¹
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1.8 1 2 1 2
## 2 1.5 1 2 1 2
## 3 1.2 1 2 1 1
## 4 0.8 0 1 0 1
## 5 0.5 0 1 0 0
## 6 0.2 0 1 0 0
## 7 -0.2 -1 0 0 0
## 8 -0.5 -1 0 0 0
## 9 -0.8 -1 0 0 -1
## 10 -1.2 -2 -1 -1 -1
## 11 -1.5 -2 -1 -1 -2
## 12 -1.8 -2 -1 -1 -2
## # ℹ abbreviated name: ¹`Nearest, round half to even`
#> # A tibble: 12 x 5
#> x `Round down` `Round up` `Round towards zero` `Nearest, round half to ev…
#> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1.8 1 2 1 2
#> 2 1.5 1 2 1 2
#> 3 1.2 1 2 1 1
#> 4 0.8 0 1 0 1
#> 5 0.5 0 1 0 0
#> 6 0.2 0 1 0 0
#> # … with 6 more rows
x <- seq(-10, 10, by = 0.5)
round2 <- function(x, to_even = TRUE) {
q <- x %/% 1
r <- x %% 1
q + (r >= 0.5)
}
x <- c(-12.5, -11.5, 11.5, 12.5)
round(x)
## [1] -12 -12 12 12
#> [1] -12 -12 12 12
round2(x, to_even = FALSE)
## [1] -12 -11 12 13
#> [1] -12 -11 12 13
x <- seq(-100.5, 100.5, by = 1)
x
## [1] -100.5 -99.5 -98.5 -97.5 -96.5 -95.5 -94.5 -93.5 -92.5 -91.5
## [11] -90.5 -89.5 -88.5 -87.5 -86.5 -85.5 -84.5 -83.5 -82.5 -81.5
## [21] -80.5 -79.5 -78.5 -77.5 -76.5 -75.5 -74.5 -73.5 -72.5 -71.5
## [31] -70.5 -69.5 -68.5 -67.5 -66.5 -65.5 -64.5 -63.5 -62.5 -61.5
## [41] -60.5 -59.5 -58.5 -57.5 -56.5 -55.5 -54.5 -53.5 -52.5 -51.5
## [51] -50.5 -49.5 -48.5 -47.5 -46.5 -45.5 -44.5 -43.5 -42.5 -41.5
## [61] -40.5 -39.5 -38.5 -37.5 -36.5 -35.5 -34.5 -33.5 -32.5 -31.5
## [71] -30.5 -29.5 -28.5 -27.5 -26.5 -25.5 -24.5 -23.5 -22.5 -21.5
## [81] -20.5 -19.5 -18.5 -17.5 -16.5 -15.5 -14.5 -13.5 -12.5 -11.5
## [91] -10.5 -9.5 -8.5 -7.5 -6.5 -5.5 -4.5 -3.5 -2.5 -1.5
## [101] -0.5 0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5
## [111] 9.5 10.5 11.5 12.5 13.5 14.5 15.5 16.5 17.5 18.5
## [121] 19.5 20.5 21.5 22.5 23.5 24.5 25.5 26.5 27.5 28.5
## [131] 29.5 30.5 31.5 32.5 33.5 34.5 35.5 36.5 37.5 38.5
## [141] 39.5 40.5 41.5 42.5 43.5 44.5 45.5 46.5 47.5 48.5
## [151] 49.5 50.5 51.5 52.5 53.5 54.5 55.5 56.5 57.5 58.5
## [161] 59.5 60.5 61.5 62.5 63.5 64.5 65.5 66.5 67.5 68.5
## [171] 69.5 70.5 71.5 72.5 73.5 74.5 75.5 76.5 77.5 78.5
## [181] 79.5 80.5 81.5 82.5 83.5 84.5 85.5 86.5 87.5 88.5
## [191] 89.5 90.5 91.5 92.5 93.5 94.5 95.5 96.5 97.5 98.5
## [201] 99.5 100.5
#> [1] -100.5 -99.5 -98.5 -97.5 -96.5 -95.5 -94.5 -93.5 -92.5 -91.5
#> [11] -90.5 -89.5 -88.5 -87.5 -86.5 -85.5 -84.5 -83.5 -82.5 -81.5
#> [21] -80.5 -79.5 -78.5 -77.5 -76.5 -75.5 -74.5 -73.5 -72.5 -71.5
#> [31] -70.5 -69.5 -68.5 -67.5 -66.5 -65.5 -64.5 -63.5 -62.5 -61.5
#> [41] -60.5 -59.5 -58.5 -57.5 -56.5 -55.5 -54.5 -53.5 -52.5 -51.5
#> [51] -50.5 -49.5 -48.5 -47.5 -46.5 -45.5 -44.5 -43.5 -42.5 -41.5
#> [61] -40.5 -39.5 -38.5 -37.5 -36.5 -35.5 -34.5 -33.5 -32.5 -31.5
#> [71] -30.5 -29.5 -28.5 -27.5 -26.5 -25.5 -24.5 -23.5 -22.5 -21.5
#> [81] -20.5 -19.5 -18.5 -17.5 -16.5 -15.5 -14.5 -13.5 -12.5 -11.5
#> [91] -10.5 -9.5 -8.5 -7.5 -6.5 -5.5 -4.5 -3.5 -2.5 -1.5
#> [101] -0.5 0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5
#> [111] 9.5 10.5 11.5 12.5 13.5 14.5 15.5 16.5 17.5 18.5
#> [121] 19.5 20.5 21.5 22.5 23.5 24.5 25.5 26.5 27.5 28.5
#> [131] 29.5 30.5 31.5 32.5 33.5 34.5 35.5 36.5 37.5 38.5
#> [141] 39.5 40.5 41.5 42.5 43.5 44.5 45.5 46.5 47.5 48.5
#> [151] 49.5 50.5 51.5 52.5 53.5 54.5 55.5 56.5 57.5 58.5
#> [161] 59.5 60.5 61.5 62.5 63.5 64.5 65.5 66.5 67.5 68.5
#> [171] 69.5 70.5 71.5 72.5 73.5 74.5 75.5 76.5 77.5 78.5
#> [181] 79.5 80.5 81.5 82.5 83.5 84.5 85.5 86.5 87.5 88.5
#> [191] 89.5 90.5 91.5 92.5 93.5 94.5 95.5 96.5 97.5 98.5
#> [201] 99.5 100.5
sum(x)
## [1] 0
#> [1] 0
sum(x)
## [1] 0
#> [1] 0
sum(round(x))
## [1] 0
#> [1] 0
sum(round2(x))
## [1] 101
#> [1] 101
The function parse_logical() parses logical values, which can appear as variations of TRUE/FALSE or 1/0.
parse_logical(c("TRUE", "FALSE", "1", "0", "true", "t", "NA"))
## [1] TRUE FALSE TRUE FALSE TRUE TRUE NA
#> [1] TRUE FALSE TRUE FALSE TRUE TRUE NA
parse_integer(c("1235", "0134", "NA"))
## [1] 1235 134 NA
#> [1] 1235 134 NA
parse_integer(c("1000", "$1,000", "10.00"))
## Warning: 2 parsing failures.
## row col expected actual
## 2 -- no trailing characters $1,000
## 3 -- no trailing characters 10.00
## [1] 1000 NA NA
## attr(,"problems")
## # A tibble: 2 × 4
## row col expected actual
## <int> <int> <chr> <chr>
## 1 2 NA no trailing characters $1,000
## 2 3 NA no trailing characters 10.00
#> Warning: 2 parsing failures.
#> row col expected actual
#> 2 -- an integer $1,000
#> 3 -- no trailing characters .00
#> [1] 1000 NA NA
#> attr(,"problems")
#> # A tibble: 2 x 4
#> row col expected actual
#> <int> <int> <chr> <chr>
#> 1 2 NA an integer $1,000
#> 2 3 NA no trailing characters .00
The function parse_number() parses numeric values. Unlike parse_integer(), the function parse_number() is more forgiving about the format of the numbers. It ignores all non-numeric characters before or after the first number, as with “$1,000.00” in the example. Within the number, parse_number() will only ignore grouping marks such as “,”. This allows it to easily parse numeric fields that include currency symbols and comma separators in number strings without any intervention by the user.
parse_number(c("1.0", "3.5", "$1,000.00", "NA", "ABCD12234.90", "1234ABC", "A123B", "A1B2C"))
## [1] 1.0 3.5 1000.0 NA 12234.9 1234.0 123.0 1.0
#> [1] 1.0 3.5 1000.0 NA 12234.9 1234.0 123.0 1.0
x <- sample(20, 100, replace = TRUE)
y <- x > 10
sum(y) # how many are greater than 10?
## [1] 43
#> [1] 38
mean(y) # what proportion are greater than 10?
## [1] 0.43
#> [1] 0.38
if (length(x)) {
# do something
}
## NULL
typeof(c(TRUE, 1L))
## [1] "integer"
#> [1] "integer"
typeof(c(1L, 1.5))
## [1] "double"
#> [1] "double"
typeof(c(1.5, "a"))
## [1] "character"
#> [1] "character"
sample(10) + 100
## [1] 109 104 110 103 105 108 107 101 106 102
#> [1] 107 104 103 109 102 101 106 110 105 108
runif(10) > 0.5
## [1] FALSE FALSE TRUE FALSE TRUE FALSE TRUE TRUE TRUE FALSE
#> [1] FALSE TRUE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE
1:10 + 1:2
## [1] 2 4 4 6 6 8 8 10 10 12
#> [1] 2 4 4 6 6 8 8 10 10 12
1:10 + 1:3
## Warning in 1:10 + 1:3: longer object length is not a multiple of shorter object
## length
## [1] 2 4 6 5 7 9 8 10 12 11
#> Warning in 1:10 + 1:3: longer object length is not a multiple of shorter object
#> length
#> [1] 2 4 6 5 7 9 8 10 12 11
c(x = 1, y = 2, z = 4)
## x y z
## 1 2 4
#> x y z
#> 1 2 4
set_names(1:3, c("a", "b", "c"))
## a b c
## 1 2 3
#> a b c
#> 1 2 3
x <- c("one", "two", "three", "four", "five")
x[c(3, 2, 5)]
## [1] "three" "two" "five"
#> [1] "three" "two" "five"
x[c(1, 1, 5, 5, 5, 2)]
## [1] "one" "one" "five" "five" "five" "two"
#> [1] "one" "one" "five" "five" "five" "two"
x[c(-1, -3, -5)]
## [1] "two" "four"
#> [1] "two" "four"
x[0]
## character(0)
#> character(0)
x <- c(10, 3, NA, 5, 8, 1, NA)
# All non-missing values of x
x[!is.na(x)]
## [1] 10 3 5 8 1
#> [1] 10 3 5 8 1
# All even (or missing!) values of x
x[x %% 2 == 0]
## [1] 10 NA 8 NA
#> [1] 10 NA 8 NA
x <- c(abc = 1, def = 2, xyz = 5)
x[c("xyz", "def")]
## xyz def
## 5 2
#> xyz def
#> 5 2
1.What does mean(is.na(x)) tell you about a vector x? What about sum(!is.finite(x))? The expression sum(!is.finite(x)) calculates the number of elements in the vector that are equal to missing (NA), not-a-number (NaN), or infinity (Inf).
sum(!is.finite(x))
## [1] 0
#> [1] 4
The function is.vector() only checks whether the object has no attributes other than names. Thus a list is a vector, But any object that has an attribute (other than names) is not.The idea behind this is that object oriented classes will include attributes, including, but not limited to “class”.
The function is.atomic() explicitly checks whether an object is one of the atomic types (“logical”, “integer”, “numeric”, “complex”, “character”, and “raw”) or NULL.
setNames(1:4, c("a", "b"))
## a b <NA> <NA>
## 1 2 3 4
#> a b <NA> <NA>
#> 1 2 3 4
purrr::set_names(c(a = 1, b = 2, c = 3), toupper)
## A B C
## 1 2 3
#> A B C
#> 1 2 3
purrr::set_names(c(a = 1, b = 2, c = 3), ~toupper(.))
## A B C
## 1 2 3
#> A B C
#> 1 2 3
The last value. Should you use [ or [[?
last_value <- function(x) {
# check for case with no length
if (length(x)) {
x[[length(x)]]
} else {
x
}
}
last_value(numeric())
## numeric(0)
#> numeric(0)
last_value(1)
## [1] 1
#> [1] 1
last_value(1:10)
## [1] 10
#> [1] 10
The elements at even numbered positions.
even_indices <- function(x) {
if (length(x)) {
x[seq_along(x) %% 2 == 0]
} else {
x
}
}
even_indices(numeric())
## numeric(0)
#> numeric(0)
even_indices(1)
## numeric(0)
#> numeric(0)
even_indices(1:10)
## [1] 2 4 6 8 10
#> [1] 2 4 6 8 10
# test using case to ensure that values not indices
# are being returned
even_indices(letters)
## [1] "b" "d" "f" "h" "j" "l" "n" "p" "r" "t" "v" "x" "z"
#> [1] "b" "d" "f" "h" "j" "l" "n" "p" "r" "t" "v" "x" "z"
Every element except the last value.
not_last <- function(x) {
n <- length(x)
if (n) {
x[-n]
} else {
# n == 0
x
}
}
not_last(1:3)
## [1] 1 2
#> [1] 1 2
not_last(1)
## numeric(0)
#> numeric(0)
not_last(numeric())
## numeric(0)
#> numeric(0)
Only even numbers (and no missing values).
even_numbers <- function(x) {
x[x %% 2 == 0]
}
even_numbers(-4:4)
## [1] -4 -2 0 2 4
#> [1] -4 -2 0 2 4
even_numbers2 <- function(x) {
x[!is.infinite(x) & !is.nan(x) & (x %% 2 == 0)]
}
even_numbers2(c(0:4, NA, NaN, Inf, -Inf))
## [1] 0 2 4 NA
#> [1] 0 2 4 NA
Why is x[-which(x > 0)] not the same as x[x <= 0]?
What happens when you subset with a positive integer that’s bigger than the length of the vector? What happens when you subset with a name that doesn’t exist?
Though not yet discussed much in this chapter, the [[ behaves differently. With an atomic vector, if [[ is given an index outside the range of the vector or an invalid name, it raises an error.
x <- list(1, 2, 3)
x
## [[1]]
## [1] 1
##
## [[2]]
## [1] 2
##
## [[3]]
## [1] 3
#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [1] 2
#>
#> [[3]]
#> [1] 3
str(x)
## List of 3
## $ : num 1
## $ : num 2
## $ : num 3
#> List of 3
#> $ : num 1
#> $ : num 2
#> $ : num 3
x_named <- list(a = 1, b = 2, c = 3)
str(x_named)
## List of 3
## $ a: num 1
## $ b: num 2
## $ c: num 3
#> List of 3
#> $ a: num 1
#> $ b: num 2
#> $ c: num 3
y <- list("a", 1L, 1.5, TRUE)
str(y)
## List of 4
## $ : chr "a"
## $ : int 1
## $ : num 1.5
## $ : logi TRUE
#> List of 4
#> $ : chr "a"
#> $ : int 1
#> $ : num 1.5
#> $ : logi TRUE
z <- list(list(1, 2), list(3, 4))
str(z)
## List of 2
## $ :List of 2
## ..$ : num 1
## ..$ : num 2
## $ :List of 2
## ..$ : num 3
## ..$ : num 4
#> List of 2
#> $ :List of 2
#> ..$ : num 1
#> ..$ : num 2
#> $ :List of 2
#> ..$ : num 3
#> ..$ : num 4
x1 <- list(c(1, 2), c(3, 4))
x2 <- list(list(1, 2), list(3, 4))
x3 <- list(1, list(2, list(3)))
a <- list(a = 1:3, b = "a string", c = pi, d = list(-1, -5))
str(a[1:2])
## List of 2
## $ a: int [1:3] 1 2 3
## $ b: chr "a string"
#> List of 2
#> $ a: int [1:3] 1 2 3
#> $ b: chr "a string"
str(a[4])
## List of 1
## $ d:List of 2
## ..$ : num -1
## ..$ : num -5
#> List of 1
#> $ d:List of 2
#> ..$ : num -1
#> ..$ : num -5
str(a[[1]])
## int [1:3] 1 2 3
#> int [1:3] 1 2 3
str(a[[4]])
## List of 2
## $ : num -1
## $ : num -5
#> List of 2
#> $ : num -1
#> $ : num -5
a$a
## [1] 1 2 3
#> [1] 1 2 3
a[["a"]]
## [1] 1 2 3
#> [1] 1 2 3
list(a, b, list(c, d), list(e, f)) list(list(list(list(list(list(a))))))
x <- tibble(a = 1:2, b = 3:4)
x[["a"]]
## [1] 1 2
#> [1] 1 2
x["a"]
## # A tibble: 2 × 1
## a
## <int>
## 1 1
## 2 2
#> # A tibble: 2 x 1
#> a
#> <int>
#> 1 1
#> 2 2
x[1]
## # A tibble: 2 × 1
## a
## <int>
## 1 1
## 2 2
#> # A tibble: 2 x 1
#> a
#> <int>
#> 1 1
#> 2 2
x[1, ]
## # A tibble: 1 × 2
## a b
## <int> <int>
## 1 1 3
#> # A tibble: 1 x 2
#> a b
#> <int> <int>
#> 1 1 3
x <- factor(c("ab", "cd", "ab"), levels = c("ab", "cd", "ef"))
typeof(x)
## [1] "integer"
#> [1] "integer"
attributes(x)
## $levels
## [1] "ab" "cd" "ef"
##
## $class
## [1] "factor"
#> $levels
#> [1] "ab" "cd" "ef"
#>
#> $class
#> [1] "factor"
x <- as.Date("1971-01-01")
unclass(x)
## [1] 365
#> [1] 365
typeof(x)
## [1] "double"
#> [1] "double"
attributes(x)
## $class
## [1] "Date"
#> $class
#> [1] "Date"
tb <- tibble::tibble(x = 1:5, y = 5:1)
typeof(tb)
## [1] "list"
#> [1] "list"
attributes(tb)
## $class
## [1] "tbl_df" "tbl" "data.frame"
##
## $row.names
## [1] 1 2 3 4 5
##
## $names
## [1] "x" "y"
#> $class
#> [1] "tbl_df" "tbl" "data.frame"
#>
#> $row.names
#> [1] 1 2 3 4 5
#>
#> $names
#> [1] "x" "y"
x <- hms::hms(3600)
class(x)
## [1] "hms" "difftime"
#> [1] "hms" "difftime"
x
## 01:00:00
#> 01:00:00
tibble(x = 1, y = 1:5)
## # A tibble: 5 × 2
## x y
## <dbl> <int>
## 1 1 1
## 2 1 2
## 3 1 3
## 4 1 4
## 5 1 5
#> # A tibble: 5 x 2
#> x y
#> <dbl> <int>
#> 1 1 1
#> 2 1 2
#> 3 1 3
#> 4 1 4
#> 5 1 5
tibble(x = 1:3, y = list("a", 1, list(1:3)))
## # A tibble: 3 × 2
## x y
## <int> <list>
## 1 1 <chr [1]>
## 2 2 <dbl [1]>
## 3 3 <list [1]>
#> # A tibble: 3 x 2
#> x y
#> <int> <list>
#> 1 1 <chr [1]>
#> 2 2 <dbl [1]>
#> 3 3 <list [1]>
Yes it is ok to have this list as a column of a tibble