R / tidyverse: вычисление стандартного отклонения по строкам - PullRequest
5 голосов
/ 24 марта 2019

Скажите, у меня есть следующие данные:

colA <- c("SampA", "SampB", "SampC")
colB <- c(21, 20, 30)
colC <- c(15, 14, 12)
colD <- c(10, 22, 18)
df <- data.frame(colA, colB, colC, colD)
df
#    colA colB colC colD
# 1 SampA   21   15   10
# 2 SampB   20   14   22
# 3 SampC   30   12   18

Я хочу получить средние значения строки и стандартные отклонения для значений в столбцах B-D.

Я могу рассчитать rowMeans следующим образом:

library(dplyr)
df %>% select(., matches("colB|colC|colD")) %>% mutate(rmeans = rowMeans(.))
#   colB colC colD   rmeans
# 1   21   15   10 15.33333
# 2   20   14   22 18.66667
# 3   30   12   18 20.00000

Но когда я пытаюсь вычислить стандартное отклонение, используя sd(), оно выдает ошибку.

df %>% select(., matches("colB|colC|colD")) %>% mutate(rsds = sapply(., sd(.)))
Error in is.data.frame(x) : 
  (list) object cannot be coerced to type 'double'

Итак, мой вопрос: как рассчитать стандартные отклонения здесь?

Редактировать: я пытался sapply() с sd() прочитав первый ответ здесь .

Дополнительное редактирование: не обязательно искать «опрятное» решение (база R тоже отлично работает).

Ответы [ 5 ]

3 голосов
/ 25 марта 2019

Вот еще один способ использования pmap для получения mean и sd

library(purrr)
library(dplyr)
library(tidur_
f1 <- function(x) tibble(Mean = mean(x), SD = sd(x))
df %>% 
  # select the numeric columns
  select_if(is.numeric) %>%
  # apply the f1 rowwise to get the mean and sd in transmute
  transmute(out = pmap(.,  ~ f1(c(...)))) %>% 
  # unnest the list column
  unnest %>%
  # bind with the original dataset
  bind_cols(df, .)
#   colA colB colC colD     Mean       SD
#1 SampA   21   15   10 15.33333 5.507571
#2 SampB   20   14   22 18.66667 4.163332
#3 SampC   30   12   18 20.00000 9.165151
по строкам
3 голосов
/ 24 марта 2019

Попробуйте это ( с использованием ), с rowSds из пакета matrixStats,

library(dplyr)
library(matrixStats)

columns <- c('colB', 'colC', 'colD')

df %>% 
  mutate(Mean= rowMeans(.[columns]), stdev=rowSds(as.matrix(.[columns])))

Возвращает

   colA colB colC colD     Mean    stdev
1 SampA   21   15   10 15.33333 5.507571
2 SampB   20   14   22 18.66667 4.163332
3 SampC   30   12   18 20.00000 9.165151

Ваши данные

colA <- c("SampA", "SampB", "SampC")
colB <- c(21, 20, 30)
colC <- c(15, 14, 12)
colD <- c(10, 22, 18)
df <- data.frame(colA, colB, colC, colD)
df
2 голосов
/ 25 марта 2019

Вы можете использовать pmap или rowwise (или группировать по colA) вместе с mutate:

library(tidyverse)
df %>% mutate(sd = pmap(.[-1], ~sd(c(...)))) # same as transform(df, sd = apply(df[-1],1,sd))
#>    colA colB colC colD       sd
#> 1 SampA   21   15   10 5.507571
#> 2 SampB   20   14   22 4.163332
#> 3 SampC   30   12   18 9.165151

df %>% rowwise() %>% mutate(sd = sd(c(colB,colC,colD)))
#> Source: local data frame [3 x 5]
#> Groups: <by row>
#> 
#> # A tibble: 3 x 5
#>   colA   colB  colC  colD    sd
#>   <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 SampA    21    15    10  5.51
#> 2 SampB    20    14    22  4.16
#> 3 SampC    30    12    18  9.17

df %>% group_by(colA) %>% mutate(sd = sd(c(colB,colC,colD)))
#> # A tibble: 3 x 5
#> # Groups:   colA [3]
#>   colA   colB  colC  colD    sd
#>   <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 SampA    21    15    10  5.51
#> 2 SampB    20    14    22  4.16
#> 3 SampC    30    12    18  9.17
2 голосов
/ 25 марта 2019

Другой подход tidyverse может быть следующим:

df %>%
 rowid_to_column() %>%
 gather(var, val, -c(colA, rowid)) %>%
 group_by(rowid) %>%
 summarise(rsds = sd(val)) %>%
 left_join(df %>%
            rowid_to_column(), by = c("rowid" = "rowid")) %>%
 select(-rowid)

   rsds colA   colB  colC  colD
  <dbl> <fct> <dbl> <dbl> <dbl>
1  5.51 SampA    21    15    10
2  4.16 SampB    20    14    22
3  9.17 SampC    30    12    18

Здесь сначала создается идентификатор строки.Во-вторых, он выполняет преобразование данных из широких в длинные, исключая «colA» и идентификатор строки.В-третьих, он группирует по идентификатору строки и рассчитывает стандартное отклонение.Наконец, он соединяет его с исходным df для идентификатора строки.

Или, альтернативно, используя rowwise() и do():

 df %>% 
 rowwise() %>%
 do(data.frame(., rsds = sd(unlist(.[2:length(.)]))))

  colA   colB  colC  colD  rsds
* <fct> <dbl> <dbl> <dbl> <dbl>
1 SampA    21    15    10  5.51
2 SampB    20    14    22  4.16
3 SampC    30    12    18  9.17
2 голосов
/ 24 марта 2019

Пакет magrittr трубы %>% не очень хороший способ обработки по строкам.
Возможно, вам нужно следующее.

df %>% 
  select(-colA) %>%
  t() %>% as.data.frame() %>%
  summarise_all(sd)
#        V1       V2       V3
#1 5.507571 4.163332 9.165151
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...