从 tibble 中选择单个列仍然 returns 一个 tibble 而不是一个向量

Selecting a single column from a tibble still returns a tibble instead of a vector

我有一个小标题叫 df:

> class(df)
[1] "tbl_df"     "tbl"        "data.frame"

现在我运行:

> sen <- df[df$my_dummy==0, "col_name"]

这个 returns 另一个小标题:

> class(sen)
[1] "tbl_df"     "tbl"        "data.frame"

为什么?

我怎样才能从中得到一个“数字”?

尝试pull

sen <- df %>%
  filter(my_dummy == 0) %>%
  pull(col_name)

并回答:为什么?

这是一个有意识的决定。您可以在小插图中阅读相关内容:Tibbles.

那里提到了“严格”​​。我有一个 data.frame,默认情况下参数 drop 设置为 TRUE,但这并不意味着在任何情况下 data.frame 都会被丢弃,你会得到向量.看这个例子:

df <- data.frame(a = 1, b = 2, c = 3)

var <- "a"

df[, var] # numeric vector

var <- c("a", "b")

df[, var] # data.frame

var 可以改变,因此 data.frame 的行为也可以改变。这种行为变化(取决于您无法预测的事情)是一个原因。

您可以尝试 $col_name 提取为向量。尝试-

sen <- df$col_name[df$my_dummy == 0]

Tibbles 更严格(为了类型安全),正如您在 @user13032723 建议的小插图中看到的那样。

要比较 tibbles 和 data.frames 的行为,请查看您从两个 classes 上的相同子集操作获得的输出:

# A tibble: 9 x 2
  expressions                                     output                 
  <chr>                                           <chr>                  
1 iris['Sepal.Length'] %>% class                  data.frame             
2 iris[,'Sepal.Length'] %>% class                 numeric  ###              
3 iris[['Sepal.Length']] %>% class                numeric                
4 iris$Sepal.Length %>% class                     numeric                
5 iris %>% pull('Sepal.Length') %>% class         numeric                
6 tibble(iris)['Sepal.Length'] %>% class          tbl_df, tbl, data.frame
7 tibble(iris)[,'Sepal.Length'] %>% class         tbl_df, tbl, data.frame ###
8 tibble(iris)[['Sepal.Length']] %>% class        numeric                
9 tibble(iris) %>% pull('Sepal.Length') %>% class numeric  

如您所见,tibbles 处理子集的方式不同。默认情况下,它们不会使用基本子集 ([x,y]) 简化对象 class。查看 table (###) 的 2 行和 7 行之间的区别。

要始终如一地从数据帧中提取向量,您可以使用 $ 提取器、双括号 [[]]pull().

代码

library(purrr)
library(dplyr)

tibble(expressions=c("iris['Sepal.Length'] %>% class",
                     "iris[,'Sepal.Length'] %>% class",
                     "iris[['Sepal.Length']] %>% class",
                     "iris$Sepal.Length %>% class",
                     "iris %>% pull('Sepal.Length') %>% class",
                     "tibble(iris)['Sepal.Length'] %>% class",
                     "tibble(iris)[,'Sepal.Length'] %>% class",
                     "tibble(iris)[['Sepal.Length']] %>% class",
                     "tibble(iris) %>% pull('Sepal.Length') %>% class"))%>%
        mutate(output=map_chr(expressions, ~eval(parse(text=.x))%>%
                                  toString))