【问题标题】:R nested for multiple if loops to generate new vectorR嵌套多个if循环以生成新向量
【发布时间】:2016-09-29 23:57:56
【问题描述】:

我有 20 名工人,每人执行 100 项任务。我已经为每个任务生成了真正的答案,这是 5 个答案中的 1 个

answers <- c("liver", "blood", "lung", "brain", "heart")
truth <- sample(answers, no.tasks, replace = TRUE, prob = c(0.2, 0.2, 0.2, 0.2, 0.2))

我的数据集包含列 workerID、taskID、truth。现在我需要生成另一个向量,我在其中模拟工人将根据特定概率回答的内容。例如,如果我对任务 1 的真值,工人 1 是“肝脏”,我希望工人 1 以高概率回答任务 1 的“肝脏”。同样,对于所有 2000 个任务的五个答案中的每一个,我都想要工人的答案。为此,我使用以下 for 和 if 循环。

for (i in nrow(dataSet)){
if (dataSet$truth[i] == "liver")
{
df <- (rep(sample(answers, no.tasks, prob = c(0.9, 0.02, 0.02, 0.02, 0.02), no.workers)))
} else if (dataSet$truth[i] == "blood")
{ 
df <-  (rep(sample(answers, no.tasks, prob = c(0.02, 0.9, 0.02, 0.02, 0.02), no.workers)))
} else if (dataSet$truth[i] == "lung")
{
df <- (rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.9, 0.02, 0.02), no.workers)))
} else if (dataSet$truth[i] == "brain")
{
df <- (rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.02, 0.9, 0.02), no.workers)))
} else if (dataSet$truth[i] == "heart")
{
df <-  (rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.02, 0.02, 0.9), no.workers)))
} else {
df <- (rep(sample(answers, no.tasks, prob = c(0.2, 0.2, 0.2, 0.2, 0.2), no.workers)))
}
}

但是,由于我的任务 1 的真相是大脑,所以输出向量 df 有很多答案是“大脑”。有人可以提示这里出了什么问题吗?

【问题讨论】:

  • 我还没有尝试运行你的代码,但是看着它,看起来你实际上并没有在每一轮存储你的结果,而是每次都覆盖df。尝试在顶部添加一条语句df &lt;- matrix(nrow = nrow(dataSet), ncol = no.tasks) 并分配您的作业df[i, ] &lt;- ...
  • 请显示预期输出。只有一个向量?每个任务每个答案一个向量?
  • @Parfait 是的,我只想要一个向量作为输出
  • 在给定示例数据的情况下,该向量应该是什么样子?这有助于我们繁殖。
  • @Barker 我这样做了,但它给了我 NA 作为值:/.

标签: r loops if-statement for-loop probability


【解决方案1】:

考虑使用包含 1,000 个元素的基础字符向量的列表进行初始化。

df <- vector("list", 2000) 

for (i in 1:nrow(dataSet)){
if (dataSet$truth[i] == "liver")
{
df[[i]] <-(rep(sample(answers, no.tasks, prob = c(0.9, 0.02, 0.02, 0.02, 0.02), no.workers)))
} else if (dataSet$truth[i] == "blood")
{ 
df[[i]] <-(rep(sample(answers, no.tasks, prob = c(0.02, 0.9, 0.02, 0.02, 0.02), no.workers)))
} else if (dataSet$truth[i] == "lung")
{
df[[i]] <-(rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.9, 0.02, 0.02), no.workers)))
} else if (dataSet$truth[i] == "brain")
{
df[[i]] <-(rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.02, 0.9, 0.02), no.workers)))
} else if (dataSet$truth[i] == "heart")
{
df[[i]] <-(rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.02, 0.02, 0.9), no.workers)))
} 
}

或者,您可以使用lapply(),它将输出与输入相同长度的列表向量(即dataSet的行),而不需要初始化:

df2 <- lapply(seq_len(nrow(dataSet)), function(i){
  if (dataSet$truth[i] == "liver")
  {
  temp <- (rep(sample(answers, no.tasks, prob = c(0.9, 0.02, 0.02, 0.02, 0.02), no.workers)))
  } else if (dataSet$truth[i] == "blood")
  { 
  temp <- (rep(sample(answers, no.tasks, prob = c(0.02, 0.9, 0.02, 0.02, 0.02), no.workers)))
  } else if (dataSet$truth[i] == "lung")
  {
  temp <- (rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.9, 0.02, 0.02), no.workers)))
  } else if (dataSet$truth[i] == "brain")
  {
  temp <- (rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.02, 0.9, 0.02), no.workers)))
  } else if (dataSet$truth[i] == "heart")
  {
  temp <- (rep(sample(answers, no.tasks, prob = c(0.02, 0.02, 0.02, 0.02, 0.9), no.workers)))
  } 
  return(temp)
})

更好的是,您可以通过匹配 answers 向量中的当前 dataSet$truth 来修剪嵌套的 if 语句,然后将概率向量中的相应索引替换为 0.9:

df3 <- lapply(seq_len(nrow(dataSet)), function(i){
  probs <- c(0.02, 0.02, 0.02, 0.02, 0.2)      
  probs[match(dataSet$truth[i], answers)] <- 0.9

  temp <- (rep(sample(answers, no.tasks, prob = probs, no.workers)))
})

【讨论】:

  • 是的,谢谢 lapply 功能正是我想要的。这很好用并且摆脱了循环,这是完美的,因为我将处理更大的数据。
  • 太棒了!如果回答有帮助并确认解决方案,请接受。此外,lapply() 在技术上仍然是一个循环,但它是一个矢量化循环,并且提供了更多的清晰度。见:stackoverflow.com/questions/2275896/…
  • 问题:得到答案后,我想将其与数据集中的答案进行比较,以计算评分者间一致性,即 kappa 值。但是,当我运行这个程序 100 次时,我得到一些 irr 是负面的。你知道为什么他们会是负面的吗?
  • 这可能需要成为一个新问题,因为我不知道您的 irr 流程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-29
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
相关资源
最近更新 更多