这个问题困扰了我很长一段时间。我总是只用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。我也很高兴听到任何有关这个问题的更好标题的建议。对我来说,这似乎总是在提问时最困难的部分。
答案 0 :(得分:2)
以下代码应该可以解决问题,它甚至会检查数据是否包含Red
和Blue
都为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