dplyr给了我不同的答案,这取决于我如何选择列
问题描述:
我可能无法理解dplyr的一些基础知识,但是看起来R的行为非常不同,具体取决于您是将列子集划分为一列数据帧还是传统向量。这里有一个例子:dplyr给了我不同的答案,这取决于我如何选择列
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
因为我的投入在技术上是相同的是我得到不同的输出告诉我,我误解了两个对象的行为的事实。有人可以请教我如何改进示例函数,以便它可以更强大地处理不同的对象?
感谢
答
首先,你与==
比较项目是不是真的一样。这可以用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"])
我唯一能想到的就是在你的example()函数中设置列名。用'df A5C1D2H2I1M1N2O1R2T1
问题似乎是'tbl_df'没有'drop = TRUE'就像'data.frame'那样,所以'mtcarsdf [,“cyl”]'不是一个向量,而是一个'tbl_df'本身。 – Frank
@Frank,我只是想提及同样的事情,并建议使用'[['代替:-) – A5C1D2H2I1M1N2O1R2T1