Подмножество строк и столбцов для data.frame и tbl_df - PullRequest
3 голосов
/ 20 сентября 2019

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

Точно так же не получается, что отфильтрованные и выбранные данные STILL представляют собой N * 1 тиббл, который отказывается играть с mean.

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

1 Ответ

2 голосов
/ 20 сентября 2019

Причина в том, что нам нужно [[ вместо [, как при [ это все еще 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

Для кода, упомянутого в посте ОП

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
...