Подмножество строк и столбцов для 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
Другие вопросы по тегам