Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
526 views
in Technique[技术] by (71.8m points)

r - Trying to use dplyr to group_by and apply scale()

Trying to use dplyr to group_by the stud_ID variable in the following data frame, as in this SO question:

> str(df)
'data.frame':   4136 obs. of  4 variables:
 $ stud_ID         : chr  "ABB112292" "ABB112292" "ABB112292" "ABB112292" ...
 $ behavioral_scale: num  3.5 4 3.5 3 3.5 2 NA NA 1 2 ...
 $ cognitive_scale : num  3.5 3 3 3 3.5 2 NA NA 1 1 ...
 $ affective_scale : num  2.5 3.5 3 3 2.5 2 NA NA 1 1.5 ...

I tried the following to obtain scale scores by student (rather than scale scores for observations across all students):

scaled_data <- 
          df %>%
              group_by(stud_ID) %>%
                  mutate(behavioral_scale_ind = scale(behavioral_scale),
                         cognitive_scale_ind = scale(cognitive_scale),
                         affective_scale_ind = scale(affective_scale))

Here is the result:

> str(scaled_data)
Classes ‘grouped_df’, ‘tbl_df’, ‘tbl’ and 'data.frame': 4136 obs. of  7 variables:
 $ stud_ID             : chr  "ABB112292" "ABB112292" "ABB112292" "ABB112292" ...
 $ behavioral_scale    : num  3.5 4 3.5 3 3.5 2 NA NA 1 2 ...
 $ cognitive_scale     : num  3.5 3 3 3 3.5 2 NA NA 1 1 ...
 $ affective_scale     : num  2.5 3.5 3 3 2.5 2 NA NA 1 1.5 ...
 $ behavioral_scale_ind: num [1:12, 1] 0.64 1.174 0.64 0.107 0.64 ...
  ..- attr(*, "scaled:center")= num 2.9
  ..- attr(*, "scaled:scale")= num 0.937
 $ cognitive_scale_ind : num [1:12, 1] 1.17 0.64 0.64 0.64 1.17 ...
  ..- attr(*, "scaled:center")= num 2.4
  ..- attr(*, "scaled:scale")= num 0.937
 $ affective_scale_ind : num [1:12, 1] 0 1.28 0.64 0.64 0 ...
  ..- attr(*, "scaled:center")= num 2.5
  ..- attr(*, "scaled:scale")= num 0.782

The three scaled variables (behavioral_scale, cognitive_scale, and affective_scale) have only 12 observations - the same number of observations for the first student, ABB112292.

What's going on here? How can I obtain scaled scores by individual?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The problem seems to be in the base scale() function, which expects a matrix. Try writing your own.

scale_this <- function(x){
  (x - mean(x, na.rm=TRUE)) / sd(x, na.rm=TRUE)
}

Then this works:

library("dplyr")

# reproducible sample data
set.seed(123)
n = 1000
df <- data.frame(stud_ID = sample(LETTERS, size=n, replace=TRUE),
                 behavioral_scale = runif(n, 0, 10),
                 cognitive_scale = runif(n, 1, 20),
                 affective_scale = runif(n, 0, 1) )
scaled_data <- 
  df %>%
  group_by(stud_ID) %>%
  mutate(behavioral_scale_ind = scale_this(behavioral_scale),
         cognitive_scale_ind = scale_this(cognitive_scale),
         affective_scale_ind = scale_this(affective_scale))

Or, if you're open to a data.table solution:

library("data.table")

setDT(df)

cols_to_scale <- c("behavioral_scale","cognitive_scale","affective_scale")

df[, lapply(.SD, scale_this), .SDcols = cols_to_scale, keyby = factor(stud_ID)] 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...