将具有是/否格式的多个列压缩到一个描述性列

时间:2012-10-15 14:37:42

标签: r

这个问题困扰了我很长一段时间。我总是只用for循环来解决它,但我认为现在是时候找到一种更快捷,更优雅的方法。

作为一个例子,假设我有一个数据框,其中包含有关项目是红色还是蓝色的信息。信息以这种方式呈现:

item.df <- data.frame(Item=seq(1,5), Red=c("Y", "Y", "N", "N", "N"), Blue=c("N", "N", "Y", "Y", "N"))

显然,这不是表示此信息的最简洁方式。我没有两个单独的红色和蓝色列,而只是想要一个包含“红色”,“蓝色”或“两个”的项目颜色列(或者NA也可以接受)。

显然,我可以通过创建一个空的Item.Color列然后通过循环遍历每一行来填充它。但我确信有更快的方法可以做到这一点。

当我是一个真正的R新手时,我试图通过以下方式来实现:

item.df$Item.Color <- if(item.df$Red=="Y"){"Red"}

但我很快就知道这不起作用,因为if语句只会读取item.df $ Red中的第一个元素。

有没有办法用do.call()或其中一个apply()函数来实现这个目的?我曾经尝试过,但我永远无法做到我想做的事情。提前感谢您提供的任何见解!

P.S。我也很高兴听到任何有关这个问题的更好标题的建议。对我来说,这似乎总是在提问时最困难的部分。

2 个答案:

答案 0 :(得分:2)

以下代码应该可以解决问题,它甚至会检查数据是否包含RedBlue都为TRUE(== "Y")的行。

item.df[["condensed"]] <- NA
item.df = within(item.df, {
  if(any(Red == "Y" & Blue == "Y")) stop("Blue and red cannot both be TRUE")
  condensed[Red == "Y"] <- "Red"
  condensed[Blue == "Y"] <- "Blue"
})

这里的技巧是获取子集的相同语法可用于赋值:

# Getting a subset from a vector
A[B > 2]
# Or assigning NA to that subset 
A[B > 2] <- NA

答案 1 :(得分:2)

我喜欢@Paul's answer,但您也可以通过将组合粘贴在一起并进行分解来轻松完成此操作。在为您的因子分配标签时,请记住默认情况下级别是字母的(因此,c("NN", "NY", "YN", "YY")):

item.df <- data.frame(Item=seq(1, 6), 
                      Red=c("Y", "Y", "N", "N", "N", "Y"), 
                      Blue=c("N", "N", "Y", "Y", "N", "Y"))

item.df$Item.Color <- factor(paste0(item.df$Red, item.df$Blue),
                             labels = c("Neither", "Blue", "Red", "Both"))
item.df
#   Item Red Blue Item.Color
# 1    1   Y    N        Red
# 2    2   Y    N        Red
# 3    3   N    Y       Blue
# 4    4   N    Y       Blue
# 5    5   N    N    Neither
# 6    6   Y    Y       Both