r - 如何在数据框中的不同子集上运行 glm 代码并使用提取的值创建新列?
问题描述
我有这段运行 glm 的代码,用于生成受试者对数字刺激列表的响应 [编码为 trochiac/iambic,0 或 1] 的“中点”,将中点保存为一个值并打印控制台中的值。
glm.1 <- glm(coderesponse~stimulus, family = binomial(link="logit"), data=data)
midpoint <- -glm.1$coefficients[1]/glm.1$coefficients[2]
cat(sprintf("file : %s\nmidpoint : %.2f",datafile,midpoint))
目前,此代码在整个数据帧上运行。我想知道如何修改此代码,以便可以在主数据框中的各个子组上运行它,并为每个子组创建一个包含这些值的新列?
例如,对于每个主题,我想为每个刺激类型“bd”、“nm”和“nm”中的每个块(1-8)生成中点值。该中点值将是每个 stimtype 中每个块的所有行的新创建列中的新值。
我们最终还希望将每个块的值聚合为包含中点值的一行(而不是保持所有行的值相同)。
我的主要数据框的一个小虚拟版本(仅包括一个主题和最多 6 个刺激):
subject <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2)
stimulus <- c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1)
block <- c(3, 3, 3, 7, 7, 7, 4, 4, 4, 8, 8, 8, 1, 1, 1, 5, 5, 5, 2, 2, 2, 6, 6, 6, 3, 3, 3, 7, 7, 7, 4, 4, 4, 8, 8, 8, 2, 2, 2, 6, 6, 6)
blockprocedure <- c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1)
stimtype <- c('bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm', 'bd', 'nd', 'nm')
blocktype <- c('mouth', 'mouth', 'mouth', 'nose', 'nose', 'nose', 'mouth', 'mouth', 'mouth', 'nose', 'nose', 'nose', 'mouth', 'mouth', 'mouth', 'nose', 'nose', 'nose', 'mouth', 'mouth', 'mouth', 'nose', 'nose', 'nose', 'mouth', 'mouth', 'mouth', 'nose', 'nose', 'nose', 'mouth', 'mouth', 'mouth', 'nose', 'nose', 'nose', 'mouth', 'mouth', 'mouth', 'nose', 'nose', 'nose')
coderesponse <- c(1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1)
dummy = data.frame(subject, stimulus, block, stimtype, blockprocedure, blocktype, coderesponse)
我最初尝试过,但显然这不是要走的路……:
dummy <- data %>%
group_by(subject, stimtype, block)
dummy$test <- NA
glm.1 <- glm(coderesponse~stimulus, family = binomial(link="logit"), data=dummy)
midpoint <- -glm.1$coefficients[1]/glm.1$coefficients[2]
dummy$test <- midpoint
我对编码很陌生,所以我希望这一切都有意义!感谢您的任何帮助/见解!
解决方案
tidyr::nest
我认为这是使用和组合的好地方purrr::map
。
事实上,正如?nest
所说,“嵌套通常对于创建每组模型很有用”。
这是一些代码:
library(dplyr)
library(tidyr)
library(purrr)
get_midpoint = function(data){
glm.1 = glm(coderesponse~stimulus, family = binomial(link="logit"), data=data)
rtn = -glm.1$coefficients[1]/glm.1$coefficients[2]
rtn
}
dummy %>%
nest(data=-c(subject, stimtype, block)) %>%
mutate(midpoint=map_dbl(data, get_midpoint))
# A tibble: 30 x 5 subject block stimtype data midpoint <dbl> <dbl> <fct> <list> <dbl> 1 1 3 bd <tibble [2 x 4]> -1.69e11 2 1 3 nd <tibble [2 x 4]> -1.69e11 3 1 3 nm <tibble [2 x 4]> -1.69e11 4 1 7 bd <tibble [2 x 4]> 3.00e 0 5 1 7 nd <tibble [2 x 4]> -1.69e11 6 1 7 nm <tibble [2 x 4]> -1.69e11 7 1 4 bd <tibble [2 x 4]> 4.00e 0 8 1 4 nd <tibble [2 x 4]> 4.00e 0 9 1 4 nm <tibble [2 x 4]> -1.96e11 10 1 8 bd <tibble [2 x 4]> 4.00e 0
在这里,nest
除了c(subject, stimtype, block)
名为data
. 然后您可以map
围绕此列应用自定义功能。由于您的函数返回一个双精度值,因此我使用了map_dbl
.
编辑
你也可以使用总结:
dummy %>%
group_by(subject, stimtype, block) %>%
summarise(midpoint = get_midpoint(tibble(coderesponse, stimulus)))
这会输出相同的结果(尽管顺序不同)。
推荐阅读
- arrays - 由于某种原因,数组(int 数组)中的第二个元素没有在外部函数中处理
- database - 将 AWS DynamoDB 与 Android 集成
- html - 在 R Shiny 中将变量解析为 HTML 文件
- algorithm - 需要帮助找到线性排序算法
- google-apps-script - 如何在谷歌脚本库中输入提示谷歌类型?
- html - 如何拥有相同大小的 3 张图像,当我切换到移动模式时,3 张图像重叠?
- sql - 在 bigquery 中查询配置单元
- graphql - 嵌套数据的平均聚合
- r - 如何在 R 中获得一个表格,其中包含时间序列中变量的 t、t-1、t-2、t-3 等的平均值?
- asp.net-core - Azure AD 身份验证后首次登录网站