【问题标题】:lm() within mutate() in group_by()group_by() 中的 mutate() 内的 lm()
【发布时间】:2017-02-24 22:17:11
【问题描述】:

我正在寻找一种方法来将一列添加到我的数据表中,该列由来自 lm(a~b) 函数的 residuals 组成,该函数针对不同级别的 c 单独计算

有人建议我研究 sort_by(c) 函数,但这似乎不适用于 lm(a~b)

我的工作示例数据如下所示:

主题、试验和 rt 列在 data.frame 内,我的目标是通过 R 函数计算 Zre_SPSS(我最初在 SPSS 中创建的)。

我试过了

data %<>% group_by (subject) %>% 
  mutate(Zre=residuals(lm(log(rt)~trial)))

但它不起作用 - Zre 被计算但不是在每个主题中单独计算,而是针对整个数据框。

谁能帮帮我?我是一个完整的 R(和一般编码)新手,所以如果这个问题是愚蠢的或duplicate,请原谅我,我可能不了解其他解决方案,或者他们不是我寻找的解决方案。最好的祝福。

根据 Ben Bolker 的要求,这里是从 excel 屏幕截图生成数据的 R 代码

#generate data
  subject<-c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3)
  subject<-factor(subject)
  trial<-c(1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,4,5,6)
  rt<-c(300,305,290,315,320,320,350,355,330,365,370,370,560,565,570,575,560,570)

#Following variable is what I would get after using SPSS code
  ZreSPSS<-c(0.4207,0.44871,-1.7779,0.47787,0.47958,-0.04897,0.45954,0.45487,-1.7962,0.43034,0.41075,0.0407,-0.6037,0.0113,0.61928,1.22038,-1.32533,0.07806)

#make data frame
  sym<-data.frame(subject, trial, rt, ZreSPSS)

【问题讨论】:

  • 您是否有机会以文本/剪切和粘贴形式而不是屏幕截图的形式发布您的示例?
  • 当然。我附上了从屏幕截图生成数据的代码
  • 您可能想查看tidyr::nestquick blog blurb
  • This 可能会有所帮助。
  • RHS 上带有 trial 的模型,并且 not 作为一个因素,似乎没有多大意义。这真的是您适合 SPSS 模型的数据吗?

标签: r dplyr lm


【解决方案1】:

这看起来像是 dplyr 0.5 的 mutate 中的一个错误,其中组内的 lm 仍会尝试使用完整的数据集。您可以改用do

sym %>% group_by(subject) %>% do(
{
    r <- resid(lm(log(rt) ~ trial, data = .))
    data.frame(., r)
})

这仍然与您的 SPSS 列不匹配,但它是您提供的数据的正确结果。您可以通过为每个主题手动拟合模型并检查残差来验证这一点。

(其他类型的残差包括用于标准化残差的 rstandard 和用于学生化残差的 rstudent。它们仍然与您的 SPSS 数字不匹配,但可能是您正在寻找的。)

【讨论】:

  • 感谢您的建议(Zre_SPSS 实际上是rstandard)。您的代码有效,但您已经看到它与 SPSS 输出不匹配。我仔细检查了它,数据是相同的,这更奇怪!我应该编辑我的问题并使用一些语法发布 SPSS 数据文件以供参考吗?
  • 我知道你一定讨厌截图,但这里有一个证明它在 spss 中的样子 [link]imgur.com/a/JHRPP[link]
  • 我刚刚发现,您的公式 rstandard(lm(log(rt) ~ trial) 匹配 SPSS 输出的学生化残差,但不匹配上面屏幕截图中的标准化残差。
  • 代替do(...) 也可以试试mutate(resid = resid(lm(data.frame(log(rt), trial))))
  • @blazej 你做了什么来让公式输出与 SPSS 给你的匹配?
【解决方案2】:

dplyr 的更高版本似乎能够处理这个问题(用dplyr 0.7.4 测试):

sym %>% group_by(subject) %>% do(
{
    r <- resid(lm(log(rt) ~ trial, data = .))
    data.frame(., r)
}) ->a

sym %>% group_by(subject) %>% mutate(

    r =  resid(lm(log(rt) ~ trial))
) ->b

all(a$r==b$r)  #->TRUE

另一个独立测试

# https://stackoverflow.com/a/40061201/2292993
# https://stackoverflow.com/q/24766450/2292993
# https://github.com/tidyverse/dplyr/issues/2177

# tested with dplyr 0.7.4

# 1) do 
df = group_by(iris,Species) %>% do({
res = resid( lm(Sepal.Length~Petal.Length+Petal.Width, data=.) )
data.frame(., res)
})

# 2) group_by + mutate
# cannot have "data=." in lm
df2 = group_by(iris,Species) %>% mutate(
res = resid( lm(Sepal.Length~Petal.Length+Petal.Width) )
)

# 3) filter + mutate
df3 = filter(iris,Species=='setosa') %>% mutate(
res = resid( lm(Sepal.Length~Petal.Length+Petal.Width, data=.) )
)
df3 = bind_rows(df3,
filter(iris,Species=='versicolor') %>% mutate(
res = resid( lm(Sepal.Length~Petal.Length+Petal.Width, data=.) )
))
df3 = bind_rows(df3,
filter(iris,Species=='virginica') %>% mutate(
res = resid( lm(Sepal.Length~Petal.Length+Petal.Width, data=.) )
))

# 4) across all rows (should not be the same)
df4 = mutate(iris,
res = resid( lm(Sepal.Length~Petal.Length+Petal.Width, data=iris) )
)

# conclusion: all the same, except df4
all(df$res==df2$res)
all(df$res==df3$res)
df$res==df4$res

【讨论】:

    猜你喜欢
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 2016-08-29
    • 1970-01-01
    • 1970-01-01
    • 2022-06-19
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多