我的数据集(dat)中有四个主要变量。
对于变量1,2和3的每个组合,我想更改反应时间,以便将第3个四分位数+ 1.5IQR以上的所有值设置为第三个四分位数+ 1.5个IQR的值。
TUK <- function (a,b,c) {
....
}
基本上,for循环逻辑是:
for (i in dat$SubjectID):
for (j in dat$Group):
for (k in dat$Object) :
TUK(i,j,k)
如何使用apply function family?
谢谢!
添加可重复的示例:
SubjectID <- c(3772113,3772468)
Group <- c("Easy","Hard")
Object <- c("A","B")
dat <- data.frame(expand.grid(SubjectID,Group,Object))
dat$RT <- rnorm(8,1500,700)
colnames(dat) <- c("SubjectID","Group","Object","RT")
TUK <- function (SUBJ,GROUP,OBJECT){
p <- dat[dat$SubjectID==SUBJ & dat$Group== GROUP & dat$Object==OBJECT, "RT"]
p[p$RT< 1000 | p$RT> 2000,] <- NA
dat[dat$SubjectID==SUBJ & dat$Group== GROUP & dat$Object==OBJECT, "RT"]<<- p
}
答案 0 :(得分:1)
您的问题很大一部分是您的TUK
功能可怕。以下是
问题:它取决于在全局环境中有一个名为dat
的数据框。更改数据的名称,它就会中断。
dat
应该是一个参数。问题:应避免全局作业<<-
。某些高级案例中有必要(例如,有时在Shiny应用程序中),但一般情况下它会使函数以非常类似于R的方式运行。
return()
一个值,并将其指定为任何其他正常R函数。问题:过于复杂。您通过传入SUBJ,GROUP和OBJECT但只使用它们来进行子集您正在尝试在您的函数内部执行dplyr
或data.table
或base::ave
擅长的“分组”位。这就好像你试图以某种方式构建你的函数,以便只能在这个特定的for
循环中嵌入使用。
dplyr
或data.table
或ave
(或甚至是for
循环)对其进行拆分应用组合。这也使您的功能更普遍有用,而不是粘合到这一特定情况。考虑到上述情况,这是一次尝试重写:
TUK2 <- function (RT){
RT[RT < 1000 | RT > 2000] <- NA
return(RT)
}
看多少简单!现在,如果我们要将此函数应用于数据中的每个GROUP:SUBJ:OBJECT分组,并将RT列替换为结果,我们使用dplyr
执行此操作:
library(dplyr)
group_by(dat, Group, SubjectID, Object) %>%
mutate(new_RT = TUK2(RT))
dplyr
对数据进行分组,即对数据进行分割,将简单函数应用于每个部分,并将它们全部组合在一起。
现在,在你的问题中,你说
对于变量1,2和3的每个组合,我想更改反应时间,以便将第3个四分位数+ 1.5IQR以上的所有值设置为第3个四分位数+ 1.5个IQR的值。
这听起来不像你的功能。仅基于此描述,我将其编码为
group_by(dat, Group, SubjectID, Object) %>%
mutate(new_RT = pmin(RT, quantile(RT, probs = 0.75) + 1.5 * IQR(RT)))
pmin
用于并行最小值,它是采用两个向量中较小的向量的矢量化方式。请尝试,例如pmin(1:10, 7)
,看看它的作用。
在这两个示例中,除非您使用dplyr
等重新分配dat <- group_by(dat, ...)
数据框,否则不会保存dplyr
数据框。这是功能性编程方式 - 没有全球任务。
另外一个注意事项:使用重写功能,您仍然可以使用循环而不是dplyr
。我不知道为什么你会 - dplyr
语法肯定更好 - 但我只想说明小构建块功能通常很有用,它是不是< / strong>“烘烤”for (sub %in% unique(dat$SubjectID)) {
for (obj %in% unique(dat$Object)) {
for (grp %in% unique(dat$Group)) {
dat[dat$SubjectID == sub &
dat$Object == obj &
dat$Group == grp, "RT"] <-
TUK2(
dat[dat$SubjectID == sub &
dat$Object == obj &
dat$Group == grp, "RT"]
)
}
}
}
以原始函数“烘焙”特定for循环的方式。
import UIKit
class ContactCell: UITableViewCell {
@IBOutlet var lblContactName: UILabel!
@IBOutlet var lblContactTitle: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}