Подмножество строк и столбцов для data.frame и tbl_df
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
игра с использованием filter
& select
? Мои попытки до сих пор бьют по стенам. Благодарен за любые золотые правила. Заранее спасибо.
dftbl %>% filter(b == 2) %>% select(a) %>% mean(na.rm = T) #NA
Это не удается таким же образом, когда отфильтрованные и выбранные данные ВСЕ ЕЩЕ являются тиблом N*1, который отказывается играть с 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
1 ответ
Причина в том, что нам нужно [[
вместо того [
как с [
это все еще tibble
с одной колонкой. В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