【问题标题】:Condition in ifelse: Value in multiple columns/variablesifelse 中的条件:多列/变量中的值
【发布时间】:2018-06-20 17:52:04
【问题描述】:

这可能很简单:

我喜欢创建条件“value in variableB or variableA”。

这是有效的:

var1 %in% c("value1", "value2") 条件:var1 是 value1 或 value2

var2 | var3 %in% 1 条件:var1 为 1 或 var2 为 1(var1 和 var2 是 0/1 的假人)

有了这些,我可以绕过重复的代码:

var1 == "value1" | var1 == "value2"

var2 == 1 | var3 == 1

我要替换的是

var4 == "value1" | var5 == "value1"

可重现的例子:

(我省略了 var1-var3)

var4 <- c("value1", "valuex")
var5 <- c("valuey", "value1")

df <- data.frame(var4, var5)

我使用 dplyr 包中的 case_when(),但它也应该适用于基础 R ifelse。

df <- df %>% mutate(newvar= case_when( CONDITION HERE ~ "value1", 
                     TRUE~"else"))

如果var1或var2中有value1,新变量应该是value1

(关于stackoverflow的第一个问题。如有任何不清楚之处,请见谅。)

【问题讨论】:

  • 您期待创建列还是filter 行?
  • var2 | var3 %in% 1 没有按照你的想法做,测试3 | 2 %in% 1
  • 感谢您的提示!刚从 Stata 来,一个人可以做gen asean4 = 1 if inlist(countryname, “Indonesia”, “Malaysia”, “Philippines”, “Thailand”),但也可以翻转gen thai = 1 if inlist(“Thailand”, country1, country2, country3)。正在寻找类似的东西。
  • 我正在寻找 if-else 语句中的条件。在var4 == "value1" | var5 == "value1 中摆脱重复的== "value1 的东西。
  • 回到这个var2 | var3 %in% 1 它似乎适用于数字变量或者我遗漏了一些东西:q1_a &lt;- c(1,0,0) q1_b &lt;- c(0,1,0) test &lt;- data.frame(q1_a, q1_b) test$q1_a | test$q1_b %in% 1 给出了&gt; [1] TRUE TRUE FALSE 这是正确的。

标签: r if-statement dplyr operators conditional-statements


【解决方案1】:

如果我们需要检查 'value1' 是否存在于每一行的任何一列中,请使用 filter_allany_vars

df %>%
  filter_all(any_vars(. =="value1"))

对于特定的列子集,使用filter_at

df %>%
   filter_at(vars(matches("var\\d+")), any_vars(.== "value1"))

对于基于多列比较创建二进制列,使用mutate_at(或mutate_all,如果需要比较所有列),reduce 将其绑定到单个逻辑/整数向量并将其绑定为列在数据集中创建新列

library(dplyr)
library(purrr)
df %>% 
  mutate_at(vars(matches("var\\d+")), funs(.=="value1")) %>% 
  reduce(`|`) %>%
  as.integer %>%
  bind_cols(df, new_var = .)

或者正如 @Nick 在 cmets 中提到的那样,我们可以使用 acrossdplyr 版本 &gt;1.0.0)代替已弃用的 mutate_at

df %>%
   mutate(across(matches("var\\d+"), ~!is.na(.)))

【讨论】:

  • 嗨@akrun,当我的funs!is.na 时,如何让mutate_at 代码工作?
  • @CharlotteJelleyman funs 现在已弃用。现在,应该是list(~ !is.na(.)))
  • 谢谢@akrun,但是如何将list(~ !is.na(.))) 合并到上述代码的其余部分中?运行reduce('|') 行时出现错误。 Error in Ops.POSIXt(.x, .y) : '|' not defined for "POSIXt" objects
  • @CharlotteJelleyman 如果没有使用dput 的可重复的小示例,很难回答。我建议发布一个问题
  • 新的 tidyverse 语法:mutate(across(matches("var\\d+"), ~!is.na(.))) %&gt;%
【解决方案2】:

var4 == "value1" | var5 == "value1" 等价于any(c(var4,var5)=="value1")

在 data.frame 中,您可以这样做:

df$new_col <- apply(df[,c("var4","var5")] == "value1",1,any)

【讨论】:

  • any(c(var4,var5)=="value1") 对我不起作用。 df &lt;- df %&gt;% mutate(newvar= case_when( any(c(var4,var5)=="value1") ~ "value1", TRUE~"else")) 和 newar 对于这两种情况都是 else 。
  • 在您的 mutate 语句中 var4 和 var5 是向量,因此 c 语句只是连接每个值,我的第一个选项适用于单个字符串。这就是为什么我在处理列的位置为您提供了第二种选择。如果您在问题中包含预期的输出,我们将能够提供更好的帮助。
  • 我一定忽略了第二个选项以及在 ifelse 中包含分配之前的部分的可能性。第二个选项适用于df &lt;- df %&gt;% mutate(newvar= case_when( apply(df[,c("var4","var5")] == "value1",1,any) ~ "value1", TRUE~"else")) 非常感谢,将节省一些不必要的代码工作!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
相关资源
最近更新 更多