vag*_*ond 5 r subset dataframe dplyr
这是一个'为什么'的问题而不是'如何'问题.
我有tibble
一个聚合的结果dplyr
> str(urls)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 144 obs. of 4 variables:
$ BRAND : chr "Bobbi Brown" "Calvin Klein" "Chanel" "Clarins" ...
$ WEBSITE : chr "http://www.bobbibrowncosmetics.com/" "http://www.calvinklein.com/shop/en/ck" "http://www.chanel.com/en_US/" "http://www.clarinsusa.com/" ...
$ domain : chr "bobbibrowncosmetics.com/" "calvinklein.com/shop/en/ck" "chanel.com/en_US/" "clarinsusa.com/" ...
$ final_domain: chr "bobbibrowncosmetics.com/" "calvinklein.com/shop/en/ck" "chanel.com/en_US/" "clarinsusa.com/" ...
Run Code Online (Sandbox Code Playgroud)
当我尝试将final_domain列提取为字符向量时,会发生以下情况:
> length(as.character(urls[ ,4]))
[1] 1
Run Code Online (Sandbox Code Playgroud)
当我改为强制数据框然后执行它时,我得到了我真正想要的东西:
> length(as.character(as.data.frame(urls)[ ,4]))
[1] 144
Run Code Online (Sandbox Code Playgroud)
在str
该tibble对比数据框的外观相同,但输出不同.我想知道为什么?
Hon*_*Ooi 13
根本原因是,当仅选择一列时,对tbl和数据帧进行子集会产生不同的结果.
[.data.frame
如果结果只有1列,则会删除维度,类似于矩阵子集的工作方式.所以结果是一个向量.[.tbl_df
将永远不会下降这样的尺寸; 它总是返回一个tbl.反过来,as.character
忽略tbl的类,将其视为普通列表.并且as.character
在列表上调用的行为如下deparse
:它返回的字符表示是可以解析并执行以重现列表的R代码.
在大多数情况下,tbl行为可以说是正确的做法,因为丢弃维度很容易导致错误:对数据帧进行子集化通常会导致另一个数据帧,但有时却不会.在这种特定情况下,它不会做你想要的.
如果要从tbl中提取列作为向量,可以使用列表样式索引:urls[[4]]
或urls$final_domain
.
我认为您问题的基本答案是 Hadley Wickham 在编写tibble 1.0 时希望[
操作员的行为保持一致。在 Wickham 的Advanced R的Subsetting 一章中,有些间接地讨论了这个决定:
了解简化和保留子集之间的区别很重要。简化子集返回可以表示输出的最简单的可能数据结构,并且在交互方面很有用,因为它通常会提供您想要的内容。保留子集可以使输出的结构与输入的结构保持一致,并且通常更适合编程,因为结果将始终是相同的类型。在对矩阵和数据帧进行子集化时省略 drop = FALSE 是最常见的编程错误来源之一。(它适用于您的测试用例,但随后有人会传入单列数据框,并且它会以一种意想不到且不清楚的方式失败。)
在这里,我们可以清楚地看到 Hadley 关心 的不一致默认行为[.data.frame
,以及为什么他会选择更改tibble 中的行为。
考虑到上述术语,很容易看出[.data.frame
运算符默认生成简化子集还是保留子集取决于输入而不是编程。例如,取一个数据框data_df
并将其子集:
data_df <- data.frame(a = runif(10), b = letters[1:10])
data_df[, 2]
data_df[, 1:2]
Run Code Online (Sandbox Code Playgroud)
在一种情况下你会得到一个向量,而在另一种情况下你会得到一个数据框。要预测输出的类型,您必须事先知道将要对多少列进行子集化(即您必须知道length(list_of_columns)
),这可能来自用户输入,或者您需要明确添加drop =
参数。因此,以下生成相同类的对象,但在第二种情况下不需要添加参数(大多数 R 用户可能不知道):
data_df[, 2, drop = FALSE]
data_df[, 1:2, drop = FALSE]
Run Code Online (Sandbox Code Playgroud)
随着tibble(或dplyr),我们都默认一致的行为,所以大家可以放心具有与该子集化当同一类对象的[
运营商无论我们有多少列返回:
library(tibble)
data_df <- tibble(a = runif(10), b = letters[1:10])
data_df[, 2]
data_df[, 1:2]
Run Code Online (Sandbox Code Playgroud)