簡體   English   中英

使用 dplyr 跨共享相似名稱的列計算按行匯總統計信息,例如平均值、最大值、最小值

[英]compute row-wise summary statistics such as mean, max, min across columns sharing similar names using dplyr

使用 R 分析數據時,我需要計算具有相似名稱(例如,相同前綴)的列的逐行匯總統計信息(平均值、最小值、最大值、標准差)。 雖然我可以使用諸如 matrixStats 之類的 package 來實現它,但我想知道是否有更優雅的方法可以使用 dplyr 來實現。 下面附上生成示例數據集的代碼和我用於計算逐行匯總統計的解決方案。 謝謝!

######SAMPEL CODE#####
library("tidyverse")
library("matrixStats")

# create a sample dataset
sample_data <- data.frame(matrix(nrow = 10, ncol = 6))
names(sample_data) <- c("ID", "score_1", "score_2", "score_3", "score_4", "score_5")
sample_data <- sample_data %>%
  mutate(ID = seq(1:10),
         score_1 = round(runif(10, 1, 5)),
         score_2 = round(runif(10, 1, 5)),
         score_3 = round(runif(10, 1, 5)),
         score_4 = round(runif(10, 1, 5)),
         score_5 = round(runif(10, 1, 5)))

score_columns <- grep("score_", names(sample_data))

sample_data <- sample_data %>% 
  mutate(mean_score = rowMeans(select(., starts_with("score_")), na.rm = TRUE),
         max_score = rowMaxs(as.matrix(sample_data[,c(score_columns)]), na.rm = TRUE),
         sd_score = rowSds(as.matrix(sample_data[,c(score_columns)]), na.rm = TRUE)) 

您可以使用 dplyr逐行操作結合c_across function來“逐行”計算這些統計信息,例如

library(tidyverse)
library(matrixStats)
#> 
#> Attaching package: 'matrixStats'
#> The following object is masked from 'package:dplyr':
#> 
#>     count

# create a sample dataset
sample_data <- data.frame(matrix(nrow = 10, ncol = 6))
names(sample_data) <- c("ID", "score_1", "score_2", "score_3", "score_4", "score_5")
sample_data <- sample_data %>%
  mutate(ID = seq(1:10),
         score_1 = round(runif(10, 1, 5)),
         score_2 = round(runif(10, 1, 5)),
         score_3 = round(runif(10, 1, 5)),
         score_4 = round(runif(10, 1, 5)),
         score_5 = round(runif(10, 1, 5)))

score_columns <- grep("score_", names(sample_data))

output <- sample_data %>% 
  mutate(mean_score = rowMeans(select(., starts_with("score_")), na.rm = TRUE),
         max_score = rowMaxs(as.matrix(sample_data[,c(score_columns)]), na.rm = TRUE),
         sd_score = rowSds(as.matrix(sample_data[,c(score_columns)]), na.rm = TRUE)) 
output
#>    ID score_1 score_2 score_3 score_4 score_5 mean_score max_score  sd_score
#> 1   1       1       5       4       3       2        3.0         5 1.5811388
#> 2   2       3       5       1       5       2        3.2         5 1.7888544
#> 3   3       2       5       3       2       4        3.2         5 1.3038405
#> 4   4       3       4       3       3       5        3.6         5 0.8944272
#> 5   5       2       3       2       2       3        2.4         3 0.5477226
#> 6   6       4       2       4       3       2        3.0         4 1.0000000
#> 7   7       2       2       1       3       1        1.8         3 0.8366600
#> 8   8       3       4       1       3       4        3.0         4 1.2247449
#> 9   9       3       2       3       4       2        2.8         4 0.8366600
#> 10 10       5       2       3       3       4        3.4         5 1.1401754

output2 <- sample_data %>%
  rowwise() %>%
  mutate(mean_score = mean(c_across(starts_with("score_"))),
         max_score = max(c_across(!!score_columns)),
         sd_score = sd(c_across(!!score_columns)))
output2
#> # A tibble: 10 × 9
#> # Rowwise: 
#>       ID score_1 score_2 score_3 score_4 score_5 mean_score max_score sd_score
#>    <int>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>      <dbl>     <dbl>    <dbl>
#>  1     1       1       5       4       3       2        3           5    1.58 
#>  2     2       3       5       1       5       2        3.2         5    1.79 
#>  3     3       2       5       3       2       4        3.2         5    1.30 
#>  4     4       3       4       3       3       5        3.6         5    0.894
#>  5     5       2       3       2       2       3        2.4         3    0.548
#>  6     6       4       2       4       3       2        3           4    1    
#>  7     7       2       2       1       3       1        1.8         3    0.837
#>  8     8       3       4       1       3       4        3           4    1.22 
#>  9     9       3       2       3       4       2        2.8         4    0.837
#> 10    10       5       2       3       3       4        3.4         5    1.14

代表 package (v2.0.1) 於 2022 年 1 月 31 日創建

由於這是一個特定於 dplyr 的解決方案,您可以在其他解決方案將失敗或需要笨拙的解決方法的情況下合並進一步的數據操作(例如filter()到 select 特定行),例如

library(tidyverse)
library(matrixStats)
#> 
#> Attaching package: 'matrixStats'
#> The following object is masked from 'package:dplyr':
#> 
#>     count

# create a sample dataset
sample_data <- data.frame(matrix(nrow = 10, ncol = 6))
names(sample_data) <- c("ID", "score_1", "score_2", "score_3", "score_4", "score_5")
sample_data <- sample_data %>%
  mutate(ID = seq(1:10),
         score_1 = round(runif(10, 1, 5)),
         score_2 = round(runif(10, 1, 5)),
         score_3 = round(runif(10, 1, 5)),
         score_4 = round(runif(10, 1, 5)),
         score_5 = round(runif(10, 1, 5)))

score_columns <- grep("score_", names(sample_data))

output <- sample_data %>%
  filter(ID < 6) %>%
  mutate(mean_score = rowMeans(select(., starts_with("score_")), na.rm = TRUE),
         max_score = rowMaxs(as.matrix(sample_data[,c(score_columns)]), na.rm = TRUE),
         sd_score = rowSds(as.matrix(sample_data[,c(score_columns)]), na.rm = TRUE)) 
#> Error: Problem with `mutate()` column `max_score`.
#> ℹ `max_score = rowMaxs(as.matrix(sample_data[, c(score_columns)]), na.rm = TRUE)`.
#> ℹ `max_score` must be size 5 or 1, not 10.


output2 <- sample_data %>%
  filter(ID < 6) %>%
  rowwise() %>%
  mutate(mean_score = mean(c_across(starts_with("score_"))),
         max_score = max(c_across(!!score_columns)),
         sd_score = sd(c_across(!!score_columns)))
output2
#> # A tibble: 5 × 9
#> # Rowwise: 
#>      ID score_1 score_2 score_3 score_4 score_5 mean_score max_score sd_score
#>   <int>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>      <dbl>     <dbl>    <dbl>
#> 1     1       5       2       5       5       1        3.6         5     1.95
#> 2     2       1       2       4       1       2        2           4     1.22
#> 3     3       1       2       2       4       5        2.8         5     1.64
#> 4     4       5       4       3       3       5        4           5     1   
#> 5     5       4       2       2       5       4        3.4         5     1.34

代表 package (v2.0.1) 於 2022 年 1 月 31 日創建

我用來回答您的問題的方式略有不同:

library("tidyverse")
library("matrixStats")

# create a sample dataset
sample_data <- data.frame(matrix(nrow = 10, ncol = 6))
names(sample_data) <- c("ID", "score_1", "score_2", "score_3", "score_4", "score_5")
sample_data <- sample_data %>%
  mutate(ID = seq(1:10),
         score_1 = round(runif(10, 1, 5)),
         score_2 = round(runif(10, 1, 5)),
         score_3 = round(runif(10, 1, 5)),
         score_4 = round(runif(10, 1, 5)),
         score_5 = round(runif(10, 1, 5)))

score_columns <- colnames(sample_data)[grep("score_", names(sample_data))]

sample_data<- sample_data %>% 
  rowwise(ID) %>% 
  mutate(mean_score = mean(c_across(score_columns[1]:length(score_columns))),
         max_score = max(c_across(score_columns[1]:length(score_columns))),
         sd_score = sd(c_across(score_columns[1]:length(score_columns))))

如果您想要更輕松地使用基函數,請嘗試以下操作:

score_columns <- grep("score_", names(sample_data))
sample_data['mean_score'] <- apply(sample_data[,score_columns], 1, mean)
sample_data['max_score'] <- apply(sample_data[,score_columns], 1, max)
sample_data['sd_score'] <- apply(sample_data[,score_columns], 1, sd)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM