【问题标题】:How do I get the number of levels of a factor in a tibble?如何获得小标题中因子的级别数?
【发布时间】:2020-08-06 22:03:11
【问题描述】:

这看起来很基本,但是现在tidyverse中的动词数量很大,我不知道该找哪个包。

这就是问题所在。我有一个小标题

df <- tibble(f1 = factor(rep(letters[1:3],5)),
             c1 = rnorm(15))

现在,如果我使用 $ 运算符,我可以轻松找出因子中有多少级别。

nlevels(df$f1)
# [1] 3

但如果我使用 [] 运算符,它会返回错误的级别数。

nlevels(df[,"f1"])
# [1] 0

现在,如果 df 是 data.frame 而不是 tibble,则 nlevels() 函数适用于 $ 运算符和 [] 运算符。

那么有没有人知道 tidyverse 相当于 nlevels() 可以在 data.frames 和 tibbles 上工作?

【问题讨论】:

  • 请注意 iris[,5] 是一个向量,但 as_tibble(iris)[,5] 仍然继承自 data.frame。这就是nlevels 失败的原因。替代方案包括:nlevels(df$f1)nlevels(df[,"f1",drop=TRUE])nlevels(df[["f1"]])

标签: r tidyverse


【解决方案1】:

详细说明timcdlucas(以及r2evans 的cmets)的答案,这里的问题是各种形式的提取运算符的行为,而不是tibble 的行为。为什么? tibble 实际上是 data.frame 的一种,正如我们在 tibble 上使用 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中有四种形式的提取操作符:[[[$@;如What is the meaning of the dollar sign $ in R function? 中所述。

第一种形式[ 可用于提取内容形式的向量、列表、矩阵或数据框。当与数据框(或 tidyverse 中的 tibble)一起使用时,它返回类型为 data.frametibble 的对象,除非包含 drop = TRUE 参数,如 r2evans 的问题 cmets 中所述。

由于[ 函数中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 时,extract 函数返回一个可用的最低类型的对象,即所有长度为 1 的范围都被删除。对于原始问题,带有提取运算符的drop = TRUE 返回一个因子,这是nlevels() 的正确输入类型。

> nlevels(aTibble[,"f1",drop=TRUE])
[1] 3

提取运算符的[[$ 形式提取单个对象,因此它们返回factor 类型的对象,这是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 对象系统构建的正式定义的对象,与此问题无关。

结论:使用 Tidyverse 时 Base R 仍然适用

根据tidyverse.org,tidyverse 是 R 包的集合,共享基本哲学、语法和数据结构。当人们熟悉 tidyverse 包系列时,就可以做到在不了解 Base R 工作原理的情况下,R 中有很多东西。

也就是说,当将 Base R 函数或 tidyverse 外部包中的函数合并到 tidyverse 风格的代码中时,了解关键的 Base R 概念非常重要。

【讨论】:

  • 谢谢@Len Greski,一个清晰而深思熟虑的答案。我必须为未来的读者接受它。
【解决方案2】:

我认为您可能需要使用[[ 而不是[,例如,

> nlevels(df[["f1"]])
[1] 3

【讨论】:

    【解决方案3】:

    df[,"f1"] 返回一个包含一列的小标题。所以你在整个 tibble 上做 nlevels 是没有意义的。

    df %>% pull('f1') %>% nlevels
    

    给你你想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2021-06-24
      • 2013-10-24
      • 2013-01-16
      • 2015-10-13
      • 1970-01-01
      相关资源
      最近更新 更多