Ярлык для вычисления среднего значения столбцов во фрейме данных

#r #sapply

Вопрос:

У меня есть следующий фрейм данных:

 Gene <- c("1","2","3","4","5","6")
> A1.1 <- c(1,1,2,4,3,5)
> A1.2 <- c(1,2,3,4,5,6)
> B1.1 <- c(2,2,3,5,5,5)
> B1.2 <- c(1,2,3,5,5,5)
> A2.1 <- c(3,2,5,6,6,6)
> A2.2 <- c(1,1,2,2,4,6)
> B2.1 <- c(2,1,4,5,7,4)
> B2.2 <- c(1,3,4,5,2,3)
> df <- data.frame(Gene,A1.1,A1.2,B1.1,B1.2,A2.1,A2.2,B2.1,B2.2)
> df
  Gene A1.1 A1.2 B1.1 B1.2 A2.1 A2.2 B2.1 B2.2
1    1    1    1    2    1    3    1    2    1
2    2    1    2    2    2    2    1    1    3
3    3    2    3    3    3    5    2    4    4
4    4    4    4    5    5    6    2    5    5
5    5    3    5    5    5    6    4    7    2
6    6    5    6    5    5    6    6    4    3
 

Я хочу рассчитать среднее значение по выборкам (столбцам) одной и той же буквы/числа для каждого гена (строки).

т. е. вычислите среднее значение каждого гена (#1-6) для обоих образцов A1, обоих образцов A2, обоих образцов B1 и обоих образцов B2.

Я знаю, что смогу проделать долгий путь, используя apply()

Экс,

 > A1_df <- data.frame(df$A1.1, df$A1.2)
> A1 <- apply(A1_df, 1, mean)
> A1
[1] 1.0 1.5 2.5 4.0 4.0 5.5
 

Но есть ли короткий способ сделать это с помощью sapply() такого, чтобы я получил новый фрейм данных, в котором столбцы теперь «A1», «A2», «B1», «B2»?

Дайте мне знать, если что-то неясно

Спасибо

Ответ №1:

Здесь мы можем использовать split.default числовые столбцы, удалив . следующие за ними цифры и в именах столбцов, чтобы разделить их на список данных.фрейм, затем выполнить цикл list с sapply и получить mean с rowMeans

 sapply(split.default(df[-1], sub("\.\d ", "", names(df)[-1])), rowMeans)
 

-выход

    A1  A2  B1  B2
1 1.0 2.0 1.5 1.5
2 1.5 1.5 2.0 2.0
3 2.5 3.5 3.0 4.0
4 4.0 4.0 5.0 5.0
5 4.0 5.0 5.0 4.5
6 5.5 6.0 5.0 3.5
 

Или измените форму на «длинный» формат pivot_longer и объединяйтесь в группы mean . Здесь names_pattern выполняется запись ( (.*) ) символов перед . цифрами и в именах столбцов, и это будет .value столбец, созданный в длинном формате

 library(dplyr)
library(tidyr)
df %>% 
   pivot_longer(cols = -Gene, names_to = ".value", 
      names_pattern = "(.*)\.\d ") %>%
   group_by(Gene) %>%
   summarise(across(everything(), mean))
# A tibble: 6 × 5
   Gene    A1    B1    A2    B2
  <int> <dbl> <dbl> <dbl> <dbl>
1     1   1     1.5   2     1.5
2     2   1.5   2     1.5   2  
3     3   2.5   3     3.5   4  
4     4   4     5     4     5  
5     5   4     5     5     4.5
6     6   5.5   5     6     3.5
 

данные

 df <- structure(list(Gene = 1:6, A1.1 = c(1L, 1L, 2L, 4L, 3L, 5L), 
    A1.2 = 1:6, B1.1 = c(2L, 2L, 3L, 5L, 5L, 5L), B1.2 = c(1L, 
    2L, 3L, 5L, 5L, 5L), A2.1 = c(3L, 2L, 5L, 6L, 6L, 6L), A2.2 = c(1L, 
    1L, 2L, 2L, 4L, 6L), B2.1 = c(2L, 1L, 4L, 5L, 7L, 4L), B2.2 = c(1L, 
    3L, 4L, 5L, 2L, 3L)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6"))
 

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

1. Код отлично работает, спасибо!