简体   繁体   English

使用粘贴在R中编写循环?

[英]Using paste to write a loop in R?

I'm trying to write this piece of code using a for loop. 我正在尝试使用for循环编写这段代码。

#Took Quiz X and 1
TookQuizX[1,1] <- nrow(Q1[Q1$anon_user_id %in% Q1$anon_user_id,])
TookQuizX[2,1] <- nrow(Q2[Q2$anon_user_id %in% Q1$anon_user_id,])
TookQuizX[3,1] <- nrow(Q3[Q3$anon_user_id %in% Q1$anon_user_id,])
TookQuizX[4,1] <- nrow(Q4[Q4$anon_user_id %in% Q1$anon_user_id,])
TookQuizX[5,1] <- nrow(Q5[Q5$anon_user_id %in% Q1$anon_user_id,])
TookQuizX[6,1] <- nrow(Q6[Q6$anon_user_id %in% Q1$anon_user_id,])

What I tried is the following 我尝试的是以下

for(i in 1:6){
  Qx<-paste("Q",i,"[Q",i,"$anon_user_id",sep="")
  TookQuizX[i,1] <- nrow(Qx %in% Q1$anon_user_id,])
}

When I run my loop I get the following error: 运行循环时,出现以下错误:

Error: unexpected ']' in:
"  Qx<-paste("Q",i,"[Q",i,"$anon_user_id",sep="")
  TookQuizX[i,1] <- nrow(Qx %in% Q1$anon_user_id,]"
> }
Error: unexpected '}' in "}

What am I doing wrong? 我究竟做错了什么?

Thanks! 谢谢!


This very simple example hopefully illustrates what i'm trying to do 这个非常简单的示例有望说明我正在尝试做的事情

TookQuizX <- matrix(data=NA,nrow=3,ncol=1)
Q1 <- data.frame(anon_user_id = c("A123", "A111", "A134", "A156"), other_stuf=999)
Q2 <- data.frame(anon_user_id = c("A123", "A234", "A111", "A256", "C521"), other_stuf=999)
Q3 <- data.frame(anon_user_id = c("A123", "A234", "A111", "A356", "B356"), other_stuf=999)

TookQuizX[1,1] <- nrow(Q1[Q1$anon_user_id %in% Q1$anon_user_id,])
TookQuizX[2,1] <- nrow(Q2[Q2$anon_user_id %in% Q1$anon_user_id,])
TookQuizX[3,1] <- nrow(Q3[Q3$anon_user_id %in% Q1$anon_user_id,])

As with many operations in R, it is easier to wrap your data frames in a list. 与R中的许多操作一样,将数据帧包装在列表中也更加容易。

Q_all <- list(Q1,Q2,Q3)

First, instead of using nrow , why don't you directly measure how many TRUE values there are in your %in% vector. 首先,不是使用nrow ,而是为什么不直接测量%in%向量中有多少个TRUE值。

TookQuizX[1,1] <- length(which(Q1$anon_user_id %in% Q1$anon_user_id))

To replace your loop, here is an example of lapply : 要替换循环,下面是lapply的示例:

TookQuizX[,1] <- unlist(lapply(Q_all, function(x) length(which(x$anon_user_id %in% Q_all[[1]]$anon_user_id))))

I assume that in the end, you want TookQuizX to be a matrix where entry i,j is the number of people who took Quiz i and also took Quiz j . 我假设最后,您希望TookQuizX是一个矩阵,其中条目i,j是参加测验i以及参加测验j的人数。 Additionally, I assume that your user ID's are unique, and no two rows in the data frame have the same user ID. 此外,我假设您的用户ID是唯一的,并且数据框中没有两行具有相同的用户ID。 Then let's extract just the user ID's from your data frames. 然后,让我们从数据框中仅提取用户ID。

anon_user_ids <- lapply(Q_all, `[[`, "anon_user_id")

One way of putting this together (and there are more efficient ways, but this is what came to mind first) would be to Map : 将这些组合在一起的一种方法(还有更有效的方法,但这是首先想到的)是Map

tmp <- Map(function(x,y) length(which(x %in% y)),
  anon_user_ids[rep(seq_along(anon_user_ids),times = length(anon_user_ids))] ,
  anon_user_ids[rep(seq_along(anon_user_ids),each = length(anon_user_ids))] )

This compares the intersection of i and j iteratively, so 1,1 , 2,1 , 3,1 , 1,2 , 2,2 and so forth. 此进行比较的交点ij迭代,所以1,12,13,11,22,2等。 Now I can put this into a matrix. 现在,我可以将其放入一个矩阵。 By default in matrices and arrays in R, vectors are assumed to be in column-major order (the first dimension varies quickest, and the last dimension varies slowest). 默认情况下,在R中的矩阵和数组中,矢量被假定为以列为主的顺序(第一个维变化最快,最后一个维变化最快)。

TookQuizX <- matrix(unlist(tmp), nrow = length(anon_user_ids))
     # [,1] [,2] [,3]
# [1,]    4    2    2
# [2,]    2    5    3
# [3,]    2    3    5      

You need to do two things. 您需要做两件事。 First, you need to recreate the commands you want to run: 首先,您需要重新创建要运行的命令:

for(i in 1:6){
  Qx <- paste("TookQuizX[1,", i, "] <- nrow(Q", i, "[Q", i,
              "$anon_user_id %in% Q1$anon_user_id,])", sep = "")
  print(Qx)
}

This loop will produce the strings you want to evaluate as code. 此循环将生成您要评估为代码的字符串。 To do that, you need to tell R to interpret the character strings as actual code. 为此,您需要告诉R将字符串解释为实际代码。 That involves parsing the text into code, and then evaluating the code. 这涉及将文本解析为代码,然后评估代码。 Modifying the first loop we get: 修改第一个循环,我们得到:

for(i in 1:6){
  Qx <- paste("TookQuizX[1,", i, "] <- nrow(Q", i, "[Q", i,
              "$anon_user_id %in% Q1$anon_user_id,])", sep = "")
  eval(parse(text = Qx))
}

Here's an example that solves a simplified version of what I think you're trying to accomplish. 这是一个示例,它解决了我认为您要完成的工作的简化版本。

x1 = 34
x2 = 65
x3 = 87
x4 = 298
x5 = 384
x6 = 234

var.names = sapply(1:6, function(i){
    paste0("x", i)
})

var.values = sapply(varnames, get)

 #x1  x2  x3  x4  x5  x6 
 #34  65  87 298 384 234 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM