使用 apply() 及其相关项替换循环以应用离群值测试(例如)
Using apply() and its correlaries to replace loops to apply outlier test (e.g.)
我有来自行为任务的数据,看起来像这样(假设数据框名为数据):
data <- data.frame(subject = c(rep(8666, 6), rep(5452, 6)), RT = c(714, 877, 665, 854, 1092, 1960, 770, 4551, 1483, 1061, 755, 1090))
data
subject RT
8666 714
8666 877
8666 665
8666 854
8666 1092
8666 1960
5452 770
5452 4551
5452 1483
5452 1061
5452 755
5452 1090
也就是说,对于这个问题,我正在研究一系列主题和反应时间。 (总共有 183 个受试者,每个受试者有 156 次试验。)使用 reshape 的 cast() 函数,我为每个受试者计算了一个值,我想用它来排除某些试验。
outl <- function(x) {
2.5 * mad(x) + median(x)
}
melteddata <- melt(data, id.vars="subject", measure.vars = "RT")
outliers <- cast(melteddata, subject ~ ., outl)
colnames(outliers)[2] <- "outlier"
输出如下:
subject outlier
1 5452 2235.635
2 8666 1517.844
...
现在,我通常这样做的方法是编写一个循环,针对每个唯一的受试者编号,将他们的 RT 与该受试者的离群值进行比较:
data$outliers <- 0
for(subject in unique(data$subject)) {
temp <- data[data$subject == subject,]
temp$outliers <- ifelse(temp$RT > outliers[outliers$subject == subject,]$outlier, 0, 1)
data[data$subject == subject,]$outliers <- temp$outliers
}
... 将 1960 年的 RTs 标记为异常值,主题 8666 和 4551 的 5452。
但是,我觉得必须有更 R 的方法来做到这一点。感觉 apply() 应该可以做同样的事情,当然这需要很长时间才能 运行 作为一个循环。有什么建议么?
编辑:
我意识到我可以使用 library(plyr) 包中的 ddply() 而不是使用 melt() 和 cast():
library(plyr)
outliers <- ddply(data, .(subject), summarize, median = median(RT), mad = mad(RT), outlier = median(RT) + 2.5 * mad(RT))
试一试。将异常值数据框转换为命名向量:
out <- outliers$outlier
names(out) <- outliers$subject
然后将其用作 table 到 select RT 列小于主题离群值的所有数据行的查找:
data[data$RT < out[as.character(data$subject)], ]
as.character
是必需的,因为主题 ID 是整数,并且您不想获取 out
的第 8666 个元素。
编辑 以添加 dplyr
解决方案:
group_by(data, subject) %>% summarize(outlier = 2.5 * mad(RT) + median(RT)) -> outliers
merge(data, outliers)
filter(data, RT < outlier)
我有来自行为任务的数据,看起来像这样(假设数据框名为数据):
data <- data.frame(subject = c(rep(8666, 6), rep(5452, 6)), RT = c(714, 877, 665, 854, 1092, 1960, 770, 4551, 1483, 1061, 755, 1090))
data
subject RT
8666 714
8666 877
8666 665
8666 854
8666 1092
8666 1960
5452 770
5452 4551
5452 1483
5452 1061
5452 755
5452 1090
也就是说,对于这个问题,我正在研究一系列主题和反应时间。 (总共有 183 个受试者,每个受试者有 156 次试验。)使用 reshape 的 cast() 函数,我为每个受试者计算了一个值,我想用它来排除某些试验。
outl <- function(x) {
2.5 * mad(x) + median(x)
}
melteddata <- melt(data, id.vars="subject", measure.vars = "RT")
outliers <- cast(melteddata, subject ~ ., outl)
colnames(outliers)[2] <- "outlier"
输出如下:
subject outlier
1 5452 2235.635
2 8666 1517.844
...
现在,我通常这样做的方法是编写一个循环,针对每个唯一的受试者编号,将他们的 RT 与该受试者的离群值进行比较:
data$outliers <- 0
for(subject in unique(data$subject)) {
temp <- data[data$subject == subject,]
temp$outliers <- ifelse(temp$RT > outliers[outliers$subject == subject,]$outlier, 0, 1)
data[data$subject == subject,]$outliers <- temp$outliers
}
... 将 1960 年的 RTs 标记为异常值,主题 8666 和 4551 的 5452。
但是,我觉得必须有更 R 的方法来做到这一点。感觉 apply() 应该可以做同样的事情,当然这需要很长时间才能 运行 作为一个循环。有什么建议么?
编辑: 我意识到我可以使用 library(plyr) 包中的 ddply() 而不是使用 melt() 和 cast():
library(plyr)
outliers <- ddply(data, .(subject), summarize, median = median(RT), mad = mad(RT), outlier = median(RT) + 2.5 * mad(RT))
试一试。将异常值数据框转换为命名向量:
out <- outliers$outlier
names(out) <- outliers$subject
然后将其用作 table 到 select RT 列小于主题离群值的所有数据行的查找:
data[data$RT < out[as.character(data$subject)], ]
as.character
是必需的,因为主题 ID 是整数,并且您不想获取 out
的第 8666 个元素。
编辑 以添加 dplyr
解决方案:
group_by(data, subject) %>% summarize(outlier = 2.5 * mad(RT) + median(RT)) -> outliers
merge(data, outliers)
filter(data, RT < outlier)