Получение средних значений по столбцам и стандартных отклонений для положительных и отрицательных значений отдельно в R

#r #dataframe

#r #dataframe

Вопрос:

Я могу получить средние значения по столбцам и стандартные отклонения (образец) фрейма данных следующим образом:

 means <- apply(df , 2, mean)
sdevs <- apply(df , 2, sd)
 

Однако мой фрейм данных содержит положительные и отрицательные значения, и мне нужно получить средние значения и стандартное отклонение для положительных и отрицательных значений отдельно

Пример ввода:

 COL1 COL2
1    1
2    1
3    1
-1   -1
-5   -1
-9   -1
 

Пример вывода:

 positive_means = [2,1]
positive_sdevs = [1,0]
negative_means = [-5,-1]
negative_sdevs = [4,0]
 

Я не хочу создавать цикл for, потому что мой фрейм данных содержит слишком много значений и столбцов.
Спасибо.

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

1. for циклы сами по себе неплохие. Это плохо или, скажем, можно улучшить, если используются циклы, хотя существуют векторизованные функции, ?colMeans см. 😉

Ответ №1:

Вы можете попробовать это, создав группу для положительных и отрицательных значений, а затем суммировать с dplyr помощью функций:

 library(dplyr)
#Code
new <- df %>% mutate(group=ifelse(COL1>0amp;COL2>0,'Pos','Neg')) %>%
  group_by(group) %>% summarise_all(list('mean'=mean,'sd'=sd))
 

Вывод:

 # A tibble: 2 x 5
  group COL1_mean COL2_mean COL1_sd COL2_sd
  <chr>     <dbl>     <dbl>   <dbl>   <dbl>
1 Neg          -5        -1       4       0
2 Pos           2         1       1       0
 

Некоторые используемые данные:

 #Data
df <- structure(list(COL1 = c(1L, 2L, 3L, -1L, -5L, -9L), COL2 = c(1L, 
1L, 1L, -1L, -1L, -1L)), class = "data.frame", row.names = c(NA, 
-6L))
 

Другим вариантом может быть использование apply() и rowSums() :

 #Code1
as.data.frame(apply(df[rowSums(df)>0,],2,function(x) {data.frame(Mean=mean(x),SD=sd(x))}))
 

Вывод:

   COL1.Mean COL1.SD COL2.Mean COL2.SD
1         2       1         1       0

#Code2
as.data.frame(apply(df[!rowSums(df)>0,],2,function(x) {data.frame(Mean=mean(x),SD=sd(x))}))
 

Вывод:

   COL1.Mean COL1.SD COL2.Mean COL2.SD
1        -5       4        -1       0
 

Ответ №2:

Вот еще один базовый вариант R, который можно добавить к отличному ответу Duck:

 as.data.frame(lapply(df, function(x) c(mean_pos = mean(x[x > 0]), 
                                       mean_neg = mean(x[x <= 0]),
                                       sd_pos   = sd(x[x > 0 ]), 
                                       sd_neg   = sd(x[x <= 0]))))
#>          COL1 COL2
#> mean_pos    2    1
#> mean_neg   -5   -1
#> sd_pos      1    0
#> sd_neg      4    0