Разрабатывая ответ от timcdlucas (и комментарии от r2evans ), проблема здесь заключается в поведении различных форм оператора извлечения, а не в поведении tibble
. Зачем? a tibble
на самом деле является разновидностью data.frame
, как показано, когда мы используем функцию str()
в таблице.
> library(dplyr)
> aTibble <- tibble(f1 = factor(rep(letters[1:3],5)),
+ c1 = rnorm(15))
>
> # illustrate that aTibble is actually a type of data frame
> str(aTibble)
tibble [15 × 2] (S3: tbl_df/tbl/data.frame)
$ f1: Factor w/ 3 levels "a","b","c": 1 2 3 1 2 3 1 2 3 1 ...
$ c1: num [1:15] -0.5829 0.3682 1.1854 -0.6309 -0.0268 ...
В R есть четыре формы оператора извлечения: [
, [[
, $
и @
; как указано в Что означает знак доллара $ в функции R? .
Первая форма, [
, может использоваться для извлечения векторов формы содержимого, списков, матриц или фреймы данных. При использовании с фреймом данных (или тибблом в тидиверсе) он возвращает объект типа data.frame
или tibble
, если не включен аргумент drop = TRUE
, как указано в комментариях к вопросу r2evans.
Поскольку значение по умолчанию drop=
в функции [
- FALSE
, отсюда следует, что df[,"f1"]
дает неожиданный или «неправильный» результат для кода, отправленного с исходным вопросом.
library(dplyr)
aTibble <- tibble(f1 = factor(rep(letters[1:3],5)),
c1 = rnorm(15))
# produces unexpected answer
nlevels(aTibble[,"f1"])
> nlevels(aTibble[,"f1"])
[1] 0
Аргумент drop =
используется при извлечении из матриц или массивов (т. Е. Любого объекта, имеющего атрибут dim
, как описано в справке для функции drop () .
> dim(aTibble)
[1] 15 2
>
Когда мы устанавливаем drop = TRUE
, функция извлечения возвращает объект самого низкого доступного типа, то есть все экстенты длиной 1. удаляются. В случае исходного вопроса drop = TRUE
с оператором извлечения возвращает коэффициент , который является правильным типом ввода для nlevels()
.
> nlevels(aTibble[,"f1",drop=TRUE])
[1] 3
Формы [[
и $
оператора извлечения извлекают один объект, поэтому они возвращают объекты типа factor
, r требуемый ввод в nlevels()
.
> str(aTibble$f1)
Factor w/ 3 levels "a","b","c": 1 2 3 1 2 3 1 2 3 1 ...
> nlevels(aTibble$f1)
[1] 3
>
> # produces expected answer
> str(aTibble[["f1"]])
Factor w/ 3 levels "a","b","c": 1 2 3 1 2 3 1 2 3 1 ...
> nlevels(aTibble[["f1"]])
[1] 3
>
Четвертая форма оператора извлечения, @
(известная как оператор слота), используется с формально определенными объектами, созданными с помощью объектной системы S4, и является не имеет отношения к этому вопросу.
Заключение: Base R все еще актуален при использовании Tidyverse
Per tidyverse.org , tidyverse представляет собой набор пакетов R, которые разделяют основную философию, грамматику и структуры данных. Когда кто-то знакомится с семейством пакетов tidyverse, можно делать много вещей в R, не понимая основ работы Base R.
Тем не менее, когда кто-то включает функции Base R или функции из пакетов за пределами tidyverse в код в стиле tidyverse, важно знать ключевые концепции Base R.