【问题标题】:R ifelse based on an observation meeting two criteriaR ifelse 基于满足两个标准的观察
【发布时间】:2019-06-21 18:44:38
【问题描述】:

是的,非常简单的问题即将让我陷入困境,因为我知道有一种合乎逻辑的方法。我有两个数据帧,并希望在第一个数据帧 0/1 中创建一个新列,具体取决于第二个数据帧中的任何行是否包含来自第一个数据帧的 col1/col2 对。

数据

df.ex1 <- data.frame('name'=c('sally', 'joe', 'ben', 'nick'), 'grade1'=c('A', 'B', 'F', 'A'))
df.ex2 <- data.frame('name'=c('jed', 'ben', 'sally', 'nick'), 'grade1'=c('A', 'F', 'A', 'C'))

> df.ex1
   name grade1
1 sally      A
2   joe      B
3   ben      F
4  nick      A

> df.ex2
   name grade1
1   jed      A
2   ben      F
3 sally      A
4  nick      C

#Expected result:

       name grade1 bin
    1 sally      A  1
    2   joe      B  0
    3   ben      F  1
    4  nick      A  0

显而易见的方法是检查第二个 df 中是否存在名称等级对:

df.ex1$bin <- ifelse(df.ex1[,1:2] %in% df.ex2[,1:2], 1, 0)

但这不起作用。为什么不?什么是正确的方法?实际上,得出正确方法的正确思维过程是什么?

注意,这显然行不通:

df.ex1$bin <- ifelse(df.ex1[,1] %in% df.ex2[,1] & df.ex1[,2] %in% df.ex2[,2], 1, 0)

【问题讨论】:

  • 这对于ifelse 来说太复杂了,因为您不只是检查来自df1 的特定namegrade1 是否在df2 中。您正在检查namegrade1 值是否在df2 在同一行中

标签: r if-statement


【解决方案1】:

您可能首先在寻找基于联接的东西:

df.ex2$bin <- 1
res <- merge(df.ex1,df.ex2,all.x = TRUE)
res$bin <- ifelse(is.na(res$bin),0,1)

> res
   name grade1 bin
1   ben      F   1
2   joe      B   0
3  nick      A   0
4 sally      A   1

使用 dplyrdata.table 等其他流行包将有许多等效方法。

【讨论】:

    【解决方案2】:

    您可以将两列与interaction 连接在一起,然后像您所做的那样使用%in%

    df.ex1$bin <- ifelse(interaction(df.ex1[,1:2]) %in% interaction(df.ex2[,1:2]), 1, 0)
    df.ex1
    #   name grade1 bin
    #1 sally      A   1
    #2   joe      B   0
    #3   ben      F   1
    #4  nick      A   0
    

    interaction 在这种情况下连接两列的因子,例如选择df.ex1[,1:2],一起组成一个向量。

    df.ex1[,1:2] #gives you a data.frame
    #   name grade1
    #1 sally      A
    #2   joe      B
    #3   ben      F
    #4  nick      A
    
    interaction(df.ex1[,1:2]) #gives you a factor
    #sally.A joe.B   ben.F   nick.A 
    

    然后将这两个因子/向量应用于%in%

    您也可以使用paste,例如:

    ifelse(do.call(paste, df.ex1[,1:2]) %in% do.call(paste, df.ex2[,1:2]), 1, 0)
    

    这里pasteinteraction的效果一样。它将两列连接在一起,形成一个向量。

    do.call(paste, df.ex1[,1:2])
    #"sally A" "joe B"   "ben F"   "nick A"
    

    【讨论】:

    • 我最终使用了另一个答案,但这似乎是最易读的。我阅读了“交互”文档,但并不真正理解——这里的“交互”是什么?只查看 2 个单元格?
    • 谢谢,我认为这是现在最有意义的,而且它是基础 R 作为奖励!
    【解决方案3】:

    您可以使用 data.table “更新连接”

    library(data.table)
    setDT(df.ex1)
    setDT(df.ex2)
    
    df.ex1[, bin := 0]
    df.ex1[df.ex2, on = .(name, grade1), bin := 1]
    
    df.ex1
    #     name grade1 bin
    # 1: sally      A   1
    # 2:   joe      B   0
    # 3:   ben      F   1
    # 4:  nick      A   0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      相关资源
      最近更新 更多