3

Data.frame 允许使用 对列子集进行操作[,默认情况下将单列/行输出删除到向量。Dplyr故意不允许这样做(似乎是因为编码是一场绝对的噩梦)。

df <- data.frame(a = c(1:5,NA), b = c(1,1,1,2,2,2))
mean(df[,"a"], na.rm = T) # 3

dftbl <- as.tbl(df)
mean(dftbl[,"a"], na.rm = T) # NA

因此,建议使用子集,[[因为这将为 dfs 和 tbl_dfs 提供统一的输出。但是:这仅适用于列或行,但不适用于行+列,如果您不检查警告(诚然这是我自己的错),可能会错过这种差异,例如:

dfresult <- mean(df[df$b == 2, "a"], na.rm = T) # 4.5
tblresult <- mean(dftbl[dftbl$b == 2, "a"], na.rm = T) # NA_real_

有没有人对行子集执行列操作有任何“最佳实践”建议?这是我应该使用&改进我的dplyr游戏的地方吗?到目前为止,我的尝试一直在碰壁。感谢任何黄金法则。提前致谢。filterselect

dftbl %>% filter(b == 2) %>% select(a) %>% mean(na.rm = T) #NA

这以同样的方式失败,过滤和选择的数据仍然是一个 N*1 tibble,它拒绝使用mean.

dftbl %>% filter(b == 2) %>% select(a) %>% as.data.frame() %>% .$a
# [1]  4  5 NA

dftbl %>% filter(b == 2) %>% select(a) %>% as.data.frame() %>% mean(.$a, na.rm = T)
# [1] NA
4

1 回答 1

2

原因是因为我们需要[[而不是[as with[它仍然是一个tibblewith one column。mean期望输入为vector

mean(dftbl[["a"]], na.rm = TRUE) 
#[1] 3

或使用$

mean(dftb$a, na.rm = TRUE) 

关于第二种情况,select还返回一个带有所选列的小标题。相反,我们可以pull使用vector

dftbl[dftbl$b == 2, "a"] %>% 
    pull(1)
#[1]  4  5 NA

或者,如果我们不想加载任何库,请使用unlist

mean(unlist(dftbl[dftbl$b == 2, "a"]), na.rm = TRUE)
#[1] 4.5

对于 OP 帖子中提到的代码

dftbl %>% 
    filter(b == 2) %>% 
    select(a)  %>%
     .$a %>%
     mean(., na.rm = TRUE)
#[1] 4.5

或与pull

dftbl %>%
    filter(b == 2) %>% 
    pull(a) %>%
    mean(na.rm = TRUE)
#[1] 4.5
于 2019-09-20T19:29:20.070 回答