【问题标题】:Using a 'complex' function within the apply family在应用系列中使用“复杂”功能
【发布时间】:2013-08-19 16:28:53
【问题描述】:

我正在尝试在tapply() 行中使用aov() 函数,但不确定它是否不可能,或者我只是编码不正确。

Factors<-c("Factor 1", "Factor 2")
Years<-c("Year 1", "Year 2", "Year 3","Year 4", "Year 5")
width<-rnorm(100)
height<-rnorm(100)

mydata<-data.frame(Years,Factors,width,height)

我想看看每年的因子水平之间是否存在差异。请注意,我的真实数据有几个因子水平,这就是我使用 ANOVA 而不是 t 检验的原因。

我可以让tapply() 执行“简单”功能,例如sum

with(mydata,tapply(width,Factors,FUN="sum"))

从简单的例子来看,我认为tapply() 的工作方式基本上是通过第二个条目Factors 对数据进行子集化,然后取第一个条目width,并将其放入任何声明的函数中.根据这个推理,我尝试了:

with(mydata,tapply(width~Factors,Years,FUN="aov"))

这会返回错误arguments must have the same length

如果可以将tapply 与需要复杂输入的功能一起使用,我该怎么做?我预计如何存储此类输出会出现问题。例如,如果我保存了 2 个 anova,我想将它们保存为单个“变量名”。

width.anova<-with(mydata,aov(width~Factors))
height.anova<-with(mydata,aov(height~Factors))

all.anovas<-c(width.anova, height.anova)

我希望能够做的事情类似于(*以下代码不起作用,只是为了显示我的意思):

#all.anovas$width.anova

显然c() 函数不起作用。我知道为了能够使用$ 语法,我应该使用数据框,但以下方法不起作用:

all.anovas<-data.frame(width.anova, height.anova)

如果有更简单的方法来获得我正在寻找的结果,非常感谢任何关于如何操作的提示。同样,我希望进行 5 次方差分析 - 比较 5 年中每一年的因子水平 1 和 2 之间的差异。实际上,我的数据有 8 年和 5 个因子水平。我还将对几个变量(如宽度和高度)进行这些方差分析。

【问题讨论】:

    标签: r anova tapply


    【解决方案1】:

    您使用了错误的功能。你可能想要更多这样的东西:

    lapply(split(mydata,mydata$Years),function(x) aov(width ~ Factors,data = x))
    

    或者您可以使用 plyr 包并执行以下操作:

    dlply(mydata,.(Years),function(x) aov(width ~ Factors,data = x))
    

    tapply 通常用于处理向量,因此对于更复杂的对象,您需要使用不同的工具。

    为了解决您的评论,可能是这样的:

    aov_fun <- function(x,vars){
        out <- vector("list",length(vars))
        names(out) <- vars
        f <- paste0(vars,"~Factors")
        for (i in seq_along(vars)){
            out[[i]] <- aov(as.formula(f[i]),data = x)
        }
        out
    }
    
    lapply(split(mydata,mydata$Years),aov_fun,vars = c('width','height'))
    

    【讨论】:

    • lapply 正是我想要的。有没有办法在 1 行内声明我希望 anova 运行的所有变量(即,将 aov(width~Factors) 替换为 aov(variables~Factors) 并以某种方式列出变量列表,或者我是否需要为每个变量单独一行变量(所以像你写的那样一行,另一个用height替换width的精确副本)?
    • 感谢您的帮助。我唯一不清楚的是代码中x 的外观和使用。我认为data = 后面应该跟要使用的数据集的名称,但是你有data=xx 作为自定义函数aov_fun 的输入。
    • @user2154249 范围。您希望aovmydata子集 上运行。如果您编写了data = mydata,R 将不会在aov_fun 的范围内找到任何具有该名称的对象,然后会继续返回并获取全局环境中的完整 数据集。这是一个非常常见的错误,会导致在整个数据集上运行相同的 aov。
    • @user2154249 所以,更重要的是,在aov_fun 中,我们正在处理的数据集的名称实际上是x
    • 如果我输入data=mydata,该函数将在整个数据集上运行,基本上使split 无用,这是有道理的。我想让我感到困惑的是x 没有在任何地方明确定义——它首先出现在function(x) 中。代码确实运行得很好——我只是想确切地知道发生了什么。我的大多数 R 问题都源于没有准确理解函数需要/将接受什么作为输入,或者函数的作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多