简体   繁体   中英

Compute grouped averages across varying numbers of columns

I have a (very large) dataframe with w ords in utterances of different size s and corpus f requencies of the words:

df <- structure(list(size = c(2, 2, 3, 3, 4, 4, 3, 3), 
                     w1 = c("come", "why", "er", "well", "i", "no", "that", "cos"), 
                     w2 = c("on","that", "i", "not", "'m", "thanks", "'s", "she"), 
                     w3 = c(NA, NA, "can", "today", "going", "a", "cool", "does"), 
                     w4 = c(NA,NA, NA, NA, "home", "lot", NA, NA), 
                     f1 = c(9699L, 6519L, 21345L, 35793L, 169024L, 39491L, 84682L, 11375L), 
                     f2 = c(33821L, 84682L,169024L, 21362L, 14016L, 738L, 107729L, 33737L), 
                     f3 = c(NA, NA,  15428L, 2419L, 10385L, 77328L, 132L, 7801L), 
                     f4 = c(NA, NA, NA, NA, 2714L, 3996L, NA, NA)), 
                row.names = c(NA, -8L), class = "data.frame")

I need to compute the averages for the different size groups across varying numbers of columns. I can do it size by size , like so, eg for size == 2 :

# calculate numbers of rows per size group:
RowsPerSize <- table(df$size) 

# make size subset:                   
df_size2 <- df[df$size == 2,] 

# calculate average `f`requencies per `size`:                    
AvFreqSize_2 <- apply(df_size2[,6:7], 2, function(x) sum(x, na.rm = T)/RowsPerSize[1])

# result:
AvFreqSize_2
     f1      f2 
 8109.0 59251.5

But that's cumbersome already for a single size and all the more so for multiple size s. I'm pretty certain there's a more economical way, probably in dplyr , where you can group_by . A humble beginning is this:

df %>%
  group_by(size) %>%
  summarise(freq = n())
# A tibble: 3 x 2
   size  freq
* <dbl> <int>
1     2     2
2     3     4
3     4     2

I had to guess a lot but I think you are looking for this:

library(tidyverse)

df %>%
  group_by(size) %>%
  summarise(across(matches("f\\d"), ~sum(.x, na.rm = T)/n()))
#> # A tibble: 3 x 5
#>    size      f1     f2     f3    f4
#>   <dbl>   <dbl>  <dbl>  <dbl> <dbl>
#> 1     2   8109  59252.     0      0
#> 2     3  38299. 82963   6445      0
#> 3     4 104258.  7377  43856.  3355


#as @Onyambu suggested, it could make more sense to use `mean()`
df %>%
  group_by(size) %>%
  summarise(across(matches("f\\d"), ~mean(.x, na.rm = T)))
#> # A tibble: 3 x 5
#>    size      f1     f2     f3    f4
#>   <dbl>   <dbl>  <dbl>  <dbl> <dbl>
#> 1     2   8109  59252.   NaN    NaN
#> 2     3  38299. 82963   6445    NaN
#> 3     4 104258.  7377  43856.  3355

Created on 2021-05-06 by the reprex package (v2.0.0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM