data.frame 和 tbl_df 的子集行和列
Subsetting rows and columns for both data.frame and tbl_df
Data.frame 允许使用 [
对列子集进行操作,默认情况下将单个 column/row 输出丢弃到向量。 Dplyr 不允许这样做,deliberately (and seemingly because 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_
有人对对行子集执行列操作有任何'best practice'建议吗?这是我应该使用 filter
和 select
改进我的 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
原因是因为我们需要 [[
而不是像 [
那样的 [
它仍然是一个只有一列的 tibble
。 mean
期望输入为 vector
mean(dftbl[["a"]], na.rm = TRUE)
#[1] 3
或使用$
mean(dftb$a, na.rm = TRUE)
关于第二种情况,select
还 returns 对所选列的提示。相反,我们可以使用 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中提到的代码post
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
Data.frame 允许使用 [
对列子集进行操作,默认情况下将单个 column/row 输出丢弃到向量。 Dplyr 不允许这样做,deliberately (and seemingly because 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_
有人对对行子集执行列操作有任何'best practice'建议吗?这是我应该使用 filter
和 select
改进我的 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
原因是因为我们需要 [[
而不是像 [
那样的 [
它仍然是一个只有一列的 tibble
。 mean
期望输入为 vector
mean(dftbl[["a"]], na.rm = TRUE)
#[1] 3
或使用$
mean(dftb$a, na.rm = TRUE)
关于第二种情况,select
还 returns 对所选列的提示。相反,我们可以使用 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中提到的代码post
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