【问题标题】:Trying to use dplyr to group_by and apply scale()尝试使用 dplyr 到 group_by 并应用 scale()
【发布时间】:2016-06-16 23:40:57
【问题描述】:

尝试在以下数据框中使用dplyrgroup_bystud_ID 变量,如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 ...

我尝试了以下方法来获得学生的量表分数(而不是所有学生的观察量表分数):

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))

结果如下:

> 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

三个缩放变量(behavioral_scalecognitive_scaleaffective_scale)只有 12 个观察值 - 与第一个学生 ABB112292 的观察值相同。

这里发生了什么?如何获得个人的比例分数?

【问题讨论】:

  • 你在dplyr 中查看过summarise() 吗?
  • 我认为您应该在分组之前进行变异,否则您会将每个学生的分数集中在他/她自己身上
  • @C8H10N4O2,在他/她自己身上,所以每个学生的观察将有 M = 0 和 SD = 1

标签: r dplyr


【解决方案1】:

问题似乎出在基础scale() 函数中,它需要一个矩阵。尝试自己编写。

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

然后这个工作:

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))

或者,如果您愿意接受data.table 解决方案:

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)] 

【讨论】:

    【解决方案2】:

    这是 dplyr 中的 known problem,已将修复合并到开发版本中,您可以通过以下方式安装它

    # install.packages("devtools")
    devtools::install_github("hadley/dplyr")
    

    在稳定版中,以下内容也应该可以工作:

    scale_this <- function(x) as.vector(scale(x))
    

    【讨论】:

    • 您好 krlmlr,鉴于此答案的年龄,可以公平地说,此行为已在后续版本更改中恢复吗?
    • 是的,我当时应该在答案中添加一个版本号。这几天在 dplyr >= 1.0.2 中,可以在列中使用矩阵没有问题,所以我怀疑原来的问题不再出现了?
    • 啊,没关系。它可以工作,但列名随后会显示为 [,1],这可能有点令人困惑。
    • 即使在管道set_colnames 之后,column1[,1] 也不会消失@
    • 要删除 [,1],您似乎可以:df%&gt;% mutate(scaled=as.vector(scale(value))df %&gt;% mutate(scaled=scale(value)[,1])
    【解决方案3】:
    df <- df %>% mutate(across(is.numeric, ~ as.numeric(scale(.))))
    

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。您可以在帮助中心找到更多关于如何写好答案的信息:stackoverflow.com/help/how-to-answer。祝你好运?
    • @novonimo 的观点始终很重要,但这里尤其很重要,因为已经有一个公认的答案,该答案已被社区验证,获得近 40 个赞成票。在什么情况下,您的方法比公认的答案更可取?您是否在利用新功能或新语法?
    猜你喜欢
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多