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 

因为我的投入在技术上是相同的是我得到不同的输出告诉我,我误解了两个对象的行为的事实。有人可以请教我如何改进示例函数,以便它可以更强大地处理不同的对象?

感谢

+0

我唯一能想到的就是在你的example()函数中设置列名。用'df A5C1D2H2I1M1N2O1R2T1

+1

问题似乎是'tbl_df'没有'drop = TRUE'就像'data.frame'那样,所以'mtcarsdf [,“cyl”]'不是一个向量,而是一个'tbl_df'本身。 – Frank

+0

@Frank,我只是想提及同样的事情,并建议使用'[['代替:-) – A5C1D2H2I1M1N2O1R2T1

首先,你与==比较项目是不是真的一样。这可以用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"])