0

新手:我有一个包含 3 列分类值的数据表,我想添加第四列,其中的值是根据前 3 列的值按行计算的。到目前为止,我有:

tC <- textConnection("Visit1    Visit2  Visit3
yes no  no
yes no  yes
yes yes yes")
data1 <- read.table(header=TRUE, tC)
close.connection(tC)
rm(tC)
data1["pattern"] <- NA

接下来我想填写第 4 列,如果 visit1、visit2 和 visit3 的值是例如“yes”、“no”和“no”,那么在 pattern 列中,NA 将被替换为“1”排。在其他语言中,这将是一个带有一些 IF 语句的 FOR 循环。我已经查看了 apply 系列,但仍然不太确定 R 中的最佳方法和语法。想法表示赞赏。

4

3 回答 3

3

我不确定这是解决此问题的最有效方法,但我们可以找到唯一行,然后为 data.frame 中的每一行找到它匹配的唯一行。因此,这个数字就是模式 ID。不过,我们必须将行折叠成单个字符串元素,否则 R 向量化会妨碍我们想要的。下面的示例使用稍微扩展的示例数据:

#  Visit1 Visit2 Visit3
#1    yes     no     no
#2    yes     no    yes
#3    yes    yes    yes
#4     no    yes     no
#5    yes     no    yes

#  Get unique combinations
pats <- unique( data1 )

#  Colapse each row to a single string element
pats <- apply( pats , 1 , paste , collapse = " " )

#do the same to your data and compare with the patterns
data1$pattern <- apply( data1 , 1 , function(x) match( paste( x , collapse = " " ) , pats ) )
#  Visit1 Visit2 Visit3 pattern
#1    yes     no     no       1
#2    yes     no    yes       2
#3    yes    yes    yes       3
#4     no    yes     no       4
#5    yes     no    yes       2
于 2013-09-09T09:21:41.253 回答
2

expand.grid假设我们使用 @SimonO101 的扩展样本数据,我建议使用factor.

首先,为三列创建我们将拥有的“是”和“否”的所有组合。

facLevs <- expand.grid(c("yes", "no"), c("yes", "no"), c("yes", "no"))
facLevs
#   Var1 Var2 Var3
# 1  yes  yes  yes
# 2   no  yes  yes
# 3  yes   no  yes
# 4   no   no  yes
# 5  yes  yes   no
# 6   no  yes   no
# 7  yes   no   no
# 8   no   no   no

现在,我们将考虑列的组合。我们可以使用do.call(paste, ...)比 更容易地做到这一点apply(mydf, ...)。我们将其转换为as.numeric以获取数字组。

mydf$pattern <- as.numeric(factor(do.call(paste, mydf[1:3]), 
                                  do.call(paste, facLevs)))
mydf
#   Visit1 Visit2 Visit3 pattern
# 1    yes     no     no       7
# 2    yes     no    yes       3
# 3    yes    yes    yes       1
# 4     no    yes     no       6
# 5    yes     no    yes       3

如您所见,pattern = 7对应于我们将在facLevs data.frame我们创建的第 7 行中找到的值。


为方便起见,这里是mydf

mydf <- structure(list(Visit1 = c("yes", "yes", "yes", "no", "yes"), 
                       Visit2 = c("no", "no", "yes", "yes", "no"), 
                       Visit3 = c("no", "yes", "yes", "no", "yes")), 
                  .Names = c("Visit1", "Visit2", "Visit3"), 
                  class = "data.frame", row.names = c("1", "2", "3", "4", "5"))
于 2013-09-09T18:17:56.627 回答
0

更新

用for循环回答:

updateRow <- function(rIndex, data1) { 
  if ((data1[rIndex, 1] == "yes") && 
      (data1[rIndex, 2] == "no") && 
      (data1[rIndex, 3] == "no")) { 
        data1[rIndex, 4] <- 1
  }   
}

for (i in c(1:3)) updateRow(i, data1); # dim(data1)[2]-1 the column number if you need to change it.

您可以根据需要更改 if 。我希望这是你想要的。

于 2013-09-09T09:26:21.850 回答