Как использовать group_by со средним и суммой в dplyr?

#r #dplyr

Вопрос:

У меня есть набор данных, похожий на тот, что приведен ниже, со 100 строками. Я хочу усреднить баллы учащихся по годам и школе. Таким образом, у меня будет один балл за 1 доллар США в 2019 году и 1 доллар США в 2020 году и т. Д. Для этого я использую этот код.

 df <- df %>%
  group_by(Year, `School Name`) %>% 
  summarise(across(everything(), .f = list(mean = mean), na.rm = TRUE))
 

Но мне нужно среднее число n. Я хочу знать, сколько студентов получили средний балл. Как мне это сделать с NAs?

Год Название школы Оценка Учащихся Оценка Учащихся
2019 ISD 1 1 NA
2020 ISD 4 4 2
2020 ISD 3 NA 3
2018 ISD 1 4 NA
2019 ISD 4 2 5
2020 ISD 4 3 2
2019 ISD 3 NA 1
2018 ISD1 2 4

Комментарии:

1. используйте summarise(n = n(), Mean = mean( Оценку ), Sum = sum( студента Оценка )) студента, если вам нужна только одна колонка

2. добавил некоторый контекст. У меня есть NAs в файле, о котором я забыл, и есть несколько столбцов оценок. Поэтому мне нужно найти среднее значение для каждого столбца, но также нужно n подсчетов

3. Вы можете использовать summarise(n = n(), across(all_of(yourcols), mean, na.rm = TRUE), across(all_of(othercols), sum, na.rm = TRUE)) n Это было бы то же самое, верно? Таким образом, вы можете использовать это за пределами across

4. Что Student Score представляют собой различные столбцы? Хотите суммировать каждый из них отдельно или в одну колонку?

Ответ №1:

Если я правильно понял, это может вам помочь

 #Libraries

library(tidyverse)
library(lubridate)

#Data

df <-
 tibble::tribble(
    ~Year, ~School.Name, ~Student.Score1, ~Student.Score2,
    2019L,      "ISD 1",             1L,             NA,
    2020L,      "ISD 4",             4L,             2L,
    2020L,      "ISD 3",             NA,             3L,
    2018L,      "ISD 1",             4L,             NA,
    2019L,      "ISD 4",             2L,             5L,
    2020L,      "ISD 4",             3L,             2L,
    2019L,      "ISD 3",             NA,             1L,
    2018L,      "ISD 1",             2L,             4L
    )

#How to

df %>% 
  group_by(Year,School.Name) %>% 
  summarise(
    n = n(),
    across(.cols = contains(".Score"),.fns = function(x)mean(x,na.rm = TRUE))
  )

# A tibble: 6 x 5
# Groups:   Year [3]
   Year School.Name     n Student.Score1 Student.Score2
  <int> <chr>       <int>          <dbl>          <dbl>
1  2018 ISD 1           2            3                4
2  2019 ISD 1           1            1              NaN
3  2019 ISD 3           1          NaN                1
4  2019 ISD 4           1            2                5
5  2020 ISD 3           1          NaN                3
6  2020 ISD 4           2            3.5              2
 

Ответ №2:

Я предполагаю Student Score , что столбцы представляют отдельных студентов, на которых следует смотреть в сочетании с другими студентами из той же школы и того же года. Если это так, то вам, вероятно, следует сначала преобразовать свои данные в длинный формат, как показано ниже:

 library(dplyr); library(tidyr)
df %>% 
  # reshape, keeping Year and School Name as keys
  pivot_longer(-c(Year, `School.Name`)) %>%
  group_by(Year, `School.Name`) %>% 
  filter(!is.na(value)) %>%
  summarise(mean = mean(value),
            n = n(), .groups = "drop")
 

Результат

    Year School.Name  mean     n
  <int> <chr>       <dbl> <int>
1  2018 ISD 1        4        1
2  2018 ISD1         3        2
3  2019 ISD 1        1        1
4  2019 ISD 3        1        1
5  2019 ISD 4        3.5      2
6  2020 ISD 3        3        1
7  2020 ISD 4        2.75     4
 

(Обратите внимание, я использовал данные как есть, но я подозреваю, что «ISD 1» и «ISD1» должны быть одним и тем же, и в этом случае вам может потребоваться сначала выполнить некоторую очистку данных.)

Исходные данные: (Обратите внимание, что столбцы оценок учащихся с уникальными именами переименовываются data.frame функцией, чтобы иметь уникальные имена, например, Студент.Оценка и Студент.Оценка.1)

 df <- data.frame(
  stringsAsFactors = FALSE,
              Year = c(2019L, 2020L, 2020L, 2018L, 2019L, 2020L, 2019L, 2018L),
       `School Name` = c("ISD 1","ISD 4","ISD 3",
                       "ISD 1","ISD 4","ISD 4","ISD 3","ISD1"),
     `Student Score` = c(1L, 4L, NA, 4L, 2L, 3L, NA, 2L),
     `Student Score` = c(NA, 2L, 3L, NA, 5L, 2L, 1L, 4L)
) 
 

Ответ №3:

Более длительное вращение может быть хорошим подходом.

 df %>% 
  pivot_longer(cols = c(-Year, -`School Name`)) %>% 
  group_by(Year, `School Name`) %>%
  summarise(mean = mean(value, na.rm = T))
 

выход

 
# A tibble: 6 x 3
# Groups:   Year [3]
   Year `School Name`  mean
  <int> <chr>         <dbl>
1  2018 ISD 1          3.33
2  2019 ISD 1          1   
3  2019 ISD 3          1   
4  2019 ISD 4          3.5 
5  2020 ISD 3          3   
6  2020 ISD 4          2.75