【问题标题】:Using match and apply in R在 R 中使用匹配和应用
【发布时间】:2019-12-03 22:04:51
【问题描述】:
> df = data.frame(id = 1:5, ch_1 = 11:15,ch_2= 10:14,selection = c(11,13,12,14,12))
> df
  id ch_1 ch_2 selection
1  1   11   10        11
2  2   12   11        13
3  3   13   12        12
4  4   14   13        14
5  5   15   14        12

鉴于此数据集,我需要一个遵循规则的附加列:

  1. 如果选择是两个选择之一(ch_1 和 ch_2),则返回选择的编号(1 或 2)
  2. 如果选择不是两个选项中的一个,则返回 3

我需要一种方法来为每一行执行此操作。对于单行,执行以下代码就可以了,但我似乎无法找到一种方法将其与 apply 一起使用以将其运行到数据帧的每一行。寻找可应用于的解决方案不仅仅是两列,而且比传统循环运行得更快

df=df[1,]

if (df$selection %in% df[,paste("ch_",1:2,sep="")]) {
  a = which(df[,paste("ch_",1:2,sep="")]==df$selection)
} else {
  a = 3
}
# OR
ifelse(df$selection %in% df[,paste("ch_",1:2,sep="")],1,3)
# OR
match(df$selection,df[,paste("ch_",1:2,sep="")])

【问题讨论】:

  • 有没有可能有多个列匹配的情况?
  • @thelatemail 不,所有列都必然不同

标签: r match apply


【解决方案1】:

将向量与== 的其他列进行比较,添加始终为TRUE 的最后一列,然后使用max.col 获取每行中第一个TRUE 的索引

max.col(cbind(df$selection == df[c("ch_1","ch_2")], TRUE), "first")
#[1] 1 3 2 1 3

这应该很容易扩展到 n 列。

【讨论】:

  • 我认为这比ifelsedplyr::case_when 更加地道和优雅,很好。
  • 接受正确答案是不够的,只需要发表评论并说明这是多么优雅。谢谢@thelatemail
  • @r2evans - 我想我记得看到过一个case_when 扩展,它可以在某处将list 作为输入,这可以绕过编写n 语句的需要。然而,我无法再次挖掘它。
【解决方案2】:

可以使用嵌套的ifelse 执行此操作,

with(df, ifelse(selection == ch_1, 1L, ifelse(selection == ch_2, 2L, 3L)))
# [1] 1 3 2 1 3

但我很少喜欢嵌套它们。如果这就是你所需要的(而且你永远不需要超过两个),那么这可能就足够了。

另一种方法是使用dplyr::case_when

with(df, dplyr::case_when(selection == ch_1 ~ 1, selection == ch_2 ~ 2, TRUE ~ 3))

如果您已经在使用该软件包,它可以在 dplyr::mutate 中轻松使用。

【讨论】:

  • 感谢@r2evans,但我的原始数据有 15 列以上。有没有一种方法我不必指定每个选择实例 == ch_1、ch_2、ch_3... 等等?
  • 是的......去@thelatemail的回答:-)
猜你喜欢
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 2018-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多