0

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

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

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

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

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

当我还是一个真正的 R 新手时,我试图通过以下方式做到这一点:

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

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

有没有办法使用 do.call() 或其中一个 apply() 函数来实现这一点?我已经尝试过了,但我永远无法让它完全按照我的意愿去做。提前感谢您提供的任何见解!

ps 我也很高兴听到任何关于这个问题的更好标题的建议。对我来说,这似乎总是提问中最难的部分。

4

2 回答 2

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
于 2012-10-15T14:50:12.683 回答
2

我喜欢@Paul 的 回答,但您也可以通过将组合粘贴在一起并进行分解来轻松做到这一点。将标签分配给您的因子时,请记住默认情况下级别是字母顺序的(因此,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
于 2012-10-15T16:19:16.787 回答