我可能无法理解dplyr的一些基础知识,但看起来R的行为会有很大不同,具体取决于您是将列作为一个列数据帧还是作为传统向量进行子集化。这是一个例子:
mtcarsdf<-tbl_df(mtcars)
example<-function(x,y) {
df<-tbl_df(data.frame(x,y))
df %>% group_by(x) %>% summarise(total=sum(y))
}
#subsetting to cyl this way gives integer vector
example(mtcars$gear,mtcarsdf$cyl)
# 3 112
# 4 56
# 5 30
#subsetting this way gives a one column data table
example(mtcars$gear,mtcarsdf[,"cyl"])
# 3 198
# 4 198
# 5 198
all(mtcarsdf$cyl==mtcarsdf[,"cyl"])
# TRUE
由于我的输入在技术上是相同的,因此我获得不同的输出这一事实告诉我,我误解了两个对象的行为方式。有人可以请教我如何改进示例函数,以便它可以更强大地处理不同的对象吗?
由于
答案 0 :(得分:3)
首先,您与==
进行比较的项目并不完全相同。这可以使用all.equal
代替==
来识别:
all.equal(mtcarsdf$cyl, mtcarsdf[, "cyl"])
## [1] "Modes: numeric, list"
## [2] "Lengths: 32, 1"
## [3] "names for current but not for target"
## [4] "Attributes: < target is NULL, current is list >"
## [5] "target is numeric, current is tbl_df"
考虑到这一点,您应该能够使用[[
提取列而不是[
来获得所需的行为。
mtcarsdf <- tbl_df(mtcars)
example<-function(x,y) {
df<-tbl_df(data.frame(x,y))
df %>% group_by(x) %>% summarise(total=sum(y))
}
example(mtcars$gear, mtcarsdf[["cyl"]])
但是,更安全的方法可能是将列重命名作为函数的一部分进行集成,如下所示:
example2 <- function(x, y) {
df <- tbl_df(setNames(data.frame(x, y), c("x", "y")))
df %>% group_by(x) %>% summarise(total = sum(y))
}
然后,以下任何一项都应该给你相同的结果。
example2(mtcars$gear, mtcarsdf$cyl)
example2(mtcars$gear, mtcarsdf[["cyl"]])
example2(mtcars$gear, mtcarsdf[, "cyl"])