【问题标题】:condition in loop in RR中的循环条件
【发布时间】:2019-03-05 04:40:00
【问题描述】:

我有一个相对简单的问题,我无法应用我在互联网上找到的解决方案。假设我们有:

set.seed(20)

data <- data.frame(month = rep(month.name, 25), 
a = rnorm(300, 0, 1), b = runif(300, 0, 7.2))

我想使用循环计算 ab 列在 month 中每个月的差异的 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-test 对正态分布非常敏感。因此,我计划在循环中使用条件,如果 shapiro 测试的 p 值小于 0.05,则需要对数据进行 log 转换;然后它将用于 f-test。

通常,我会在 ifelse 条件下执行此操作,但我不太确定如何在这里使用它。 请问这里有什么帮助吗?

【问题讨论】:

  • 您确定数据是正数吗?只能针对正值计算日志,并且您的列 a 是从法线中提取的。
  • 是的,数据是肯定的。为了使示例更具代表性,我还创建了一个具有标准化值的列。

标签: r loops if-statement normal-distribution


【解决方案1】:

我相信下面的代码可以满足您的需求。它使用*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。像这样,结果列表sp中的每个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]))
})

最后,将提取函数[[ 应用于测试结果很简单。这是有效的,因为 R 中的假设测试函数返回类 "htest" 的对象,这些对象只不过是列表。最后一个提取循环被注释掉了。

ftest <- sapply(vartest_list, '[[', 'f')
pval <- sapply(vartest_list, '[[', 'p.value')
#month <- sapply(vartest_list, '[[', 'month')

【讨论】:

  • 感谢您的宝贵时间。我对 sapply 或 lapply 不是很熟悉。在 sapply 的情况下,例如“[[”是为了什么?我知道与列表有关,但我不确定为什么方括号也不需要关闭。
  • @AndreiNiță '[[' 是一个函数,一个提取函数。请参阅?Extract 并注意与?'[[' 相同的帮助页面。我的回答中的sapply 调用将函数[[ 应用于列表vartest_list 的每个成员,传递参数'f''p.value'。这些是要提取的子列表成员。 (每个vartest_list 成员都是"htest" 类的列表,因此请使用列表提取函数来获取其成员。)
  • @AndreiNiță 尝试以下操作:tmp &lt;- vartest_list[[1]]。现在tmp 是第一次测试的结果。然后tmp[['p.value']]。第二个sapply 以一种紧凑的方式循环所有vartest_list 成员。没有tmp 的另一种查看方式是vartest_list[[1]][['p.value']],然后是vartest_list[[2]][['p.value']],然后等等。
  • 我现在明白了。再次感谢您的宝贵时间和广泛的回答。我今天稍微丰富了我在 R 方面的知识:)
猜你喜欢
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
  • 2014-11-19
  • 2021-05-06
  • 2022-12-18
  • 2020-11-26
  • 1970-01-01
  • 2020-11-07
相关资源
最近更新 更多