【问题标题】:Subsetting rows and columns for both data.frame and tbl_df为 data.frame 和 tbl_df 设置行和列的子集
【发布时间】:2020-01-21 20:31:30
【问题描述】:

Data.frame 允许使用 [ 对列子集进行操作,默认情况下将单列/行输出删除到向量。 Dplyr 不允许这样做,deliberately(似乎是因为coding was an absolute nightmare)。

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_

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

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

【问题讨论】:

    标签: r dplyr subset tbl


    【解决方案1】:

    原因是因为我们需要[[ 而不是[,就像[ 它仍然是一个带有一列的tibblemean 期望输入为 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
    

    【讨论】:

    • 感谢 akrun,很好的方法概述。在倒数第二个代码块(这是我将来尝试使用的方法,或取消列表)中,一个人既需要 select(a) 也需要 .$a 似乎不直观,但我想这仍然是我的头脑周围的小东西永远不会掉……但是为什么 select(a) %>% mean(.$a, na.rm = T) 不起作用?大概 (., 在 [你的代码] 的平均行中,从上面的行中提取不变的结果,即 .$a (4 5 NA) 所以不应该 mean() 工作相同吗?干杯!
    • @dez93_2000。这是由于评估块。您可以使用{} 将其作为单个块,即select(a) %&gt;% {mean(.$a, na.rm = T)} 运算符具有优先权
    • 很有趣,再次感谢。只看到 {} 在一些 gganimate 脚本中使用,我想我会阅读以了解更多信息。干杯
    猜你喜欢
    • 2016-04-01
    • 2015-05-02
    • 2011-03-22
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 2012-04-16
    相关资源
    最近更新 更多