我有一个相对简单的问题,我无法应用我在互联网上找到的解决方案。假设我们有:
set.seed(20)
data <- data.frame(month = rep(month.name, 25),
a = rnorm(300, 0, 1), b = runif(300, 0, 7.2))我想使用循环计算、a、和b-列之间方差的f检验,在月中,每个月的方差都是f检验。这是我通过使用以下方法完成的:
# create some empty vectors to fill in later
pval <- as.double()
ftest <- as.double()
month <- as.character()
# looping through the months
for (i in unique(data$month)){
print(i)
# sh.1 <- shapiro.test(data$a[data$month==i])
# sh.1[2] > 0.05 # apply log if it's smaller than 0.05
# sh.2 <- shapiro.test(data$b[data$month==i])
# sh.2[2] > 0.05 # apply log if it's smaller than 0.05
var.t <- var.test(data$a[data$month==i], data$b[data$month==i])
f <- round(var.t[[1]],2)
p <- round(var.t$p.value,2)
ftest <- append(ftest, f)
pval <- append(pval, p)
month <- append(month, i)
}然而,据我所知,f检验对正态分布非常敏感.因此,我计划使用一个条件进入循环,如果shapiro测试的p值小于0.05,则需要对数据进行日志转换;然后将其用于f检验。
通常情况下,我会在ifelse条件下这样做,但我不太确定如何在这里使用它。这里有什么帮助吗?
发布于 2019-03-04 20:40:00
我相信下面的代码能做你想做的事。它使用*apply循环,而不是for循环,以提高代码的可读性(我认为)。
首先,我将重新创建数据,并确保列a都是正数。
set.seed(20)
data <- data.frame(month = rep(month.name, 25),
a = rnorm(300, 0, 1), b = runif(300, 0, 7.2))
data$a <- abs(data$a)现在,我没有循环遍历month的唯一值,而是将data.frame除以该变量。就像这样,结果列表中的每个df都已经是每个月所有行的df。
sp <- split(data, data$month)
sp <- sp[order(order(month.name))]如果有必要,数据就是在这里进行log转换的。
sp <- lapply(sp, function(DF){
if(shapiro.test(DF[["a"]])$p.value < 0.05) DF[["a"]] <- log(DF[["a"]])
if(shapiro.test(DF[["b"]])$p.value < 0.05) DF[["b"]] <- log(DF[["b"]])
DF
})lapply你想要的测试,var.test,所有这些data.frames。
vartest_list <- lapply(sp, function(DF){
var.t <- var.test(DF[["a"]], DF[["b"]])
list(f = var.t[[1]],
p.value = var.t$p.value,
month = as.character(DF[["month"]][1]))
})最后,将提取函数[[应用于测试结果是一个简单的问题。这是因为假设测试了类"htest"的R返回对象中的函数,这些对象只不过是列表。最后一个提取循环被注释掉。
ftest <- sapply(vartest_list, '[[', 'f')
pval <- sapply(vartest_list, '[[', 'p.value')
#month <- sapply(vartest_list, '[[', 'month')https://stackoverflow.com/questions/54984541
复制相似问题