【问题标题】:R: Matching rows by two columnsR:按两列匹配行
【发布时间】:2019-03-23 17:45:20
【问题描述】:

我目前正在尝试找出一种矢量化方式来匹配同一行中的两个值。我有以下两个简化的数据框:

# Dataframe 1: Displaying all my observations
df1 <- data.frame(c(1, 2, 3, 4, 5, 6, 7, 8),
                  c("A", "B", "C", "D", "A", "B", "A", "C"), 
                  c("B", "E", "D", "A", "C", "A", "D", "A"))
colnames(df1) <- c("ID", "Number1", "Number2")

> df1
  ID Number1 Number2
1  1       A       B
2  2       B       E
3  3       C       D
4  4       D       A
5  5       A       C
6  6       B       A
7  7       A       D
8  8       C       A

# Dataframe 2: Matrix of observations I am interested in
df2 <- matrix(c("A", "B",
                "D", "A",
                "C", "B",
                "E", "D"),
              ncol = 2,
              byrow = TRUE)

> df2
     [,1] [,2]
[1,] "A"  "B" 
[2,] "D"  "A" 
[3,] "C"  "B" 
[4,] "E"  "D" 

我想要完成的是在 df1 中创建一个新列,仅当 df2 中存在确切组合时才声明 TRUE(例如 ID = 1 等同于 df2 中的第一行,因为它们都包含 A和 B)。此外,如果有快捷方式,如果数字反转,我也希望状态为 TRUE,即 df1$Number1 匹配 df2[i,2] 并且 df1$Number2 匹配 df2[i,1] (例如对于 ID = 7,df1中的组合为A,D,df2中的组合为D,A --> TRUE)。

我想要的输出如下所示:

> df1
  ID Number1 Number2 Status
1  1       A       B   TRUE
2  2       B       E  FALSE
3  3       C       D  FALSE
4  4       D       A   TRUE
5  5       A       C  FALSE
6  6       B       A  TRUE
7  7       A       D  TRUE
8  8       C       A  FALSE

到目前为止,我得到的只是:

for (i in 1:nrow(df1)) {
  for (j in 1:nrow(df2)) {
    Status <- ifelse(df1$Number1[i] %in% df2[j,1] && 
                     df1$Number2[i] %in% df2[j,2], TRUE, FALSE)
    StatusComb[i,j] <- Status
  }
  df1$Status[i] <- ifelse(any(StatusComb[i,]) == TRUE, TRUE, FALSE)
}

它的效率真​​的很低(你可以清楚地告诉我我是 R 新手)而且看起来也不是很好。我将不胜感激!

【问题讨论】:

    标签: r match


    【解决方案1】:

    一种方法是将merge 东西放在一起。

    调整您的数据,考虑反转标签,我将反转 df2 并对其进行 rbind:

    df2 <- rbind.data.frame(df2, df2[,c(2,1)])
    colnames(df2) <- c("Number1", "Number2")
    df2$a <- TRUE
    df2
    #   Number1 Number2    a
    # 1       A       B TRUE
    # 2       D       A TRUE
    # 3       C       B TRUE
    # 4       E       D TRUE
    # 5       B       A TRUE
    # 6       A       D TRUE
    # 7       B       C TRUE
    # 8       D       E TRUE
    

    我添加了a,以便将其合并。从那里:

    df3 <- merge(df1, df2, all.x = TRUE)
    df3$a <- !is.na(df3$a)
    df3[ order(df3$ID), ]
    #   Number1 Number2 ID     a
    # 1       A       B  1  TRUE
    # 5       B       E  2 FALSE
    # 7       C       D  3 FALSE
    # 8       D       A  4  TRUE
    # 2       A       C  5 FALSE
    # 4       B       A  6  TRUE
    # 3       A       D  7  TRUE
    # 6       C       A  8 FALSE
    

    如果您在!is.na(df3$a) 之前查看它,您会发现该列完全是TRUE 和NA(NA 不存在于df2 中);如果这对您来说足够了,那么您可以省略中间步骤。 order 步骤只是因为不能保证 merge 的行顺序(实际上我发现它总是不方便地不同)。由于它之前是由ID 订购的,所以我恢复了它,但这完全是为了美观,以匹配您想要的输出。

    【讨论】:

      【解决方案2】:

      您可以按以下字母顺序定义要搜索的combination 变量:

      combination <- apply(df2, 1, function(x) {
        paste(sort(x), collapse = '')
      })
      combination
      [1] "AB" "AD" "BC" "DE"
      

      然后根据 Number 字段的串联对 Status 字段进行变异

      library(dplyr)
      df1 %>%
        rowwise() %>%
        mutate(S = paste(sort(c(Number1, Number2)), collapse = "")) %>%
        mutate(Status = ifelse(S %in% combination, TRUE, FALSE))
      Source: local data frame [8 x 5]
      Groups: <by row>
      
      # A tibble: 8 x 5
           ID Number1 Number2 S     Status
        <dbl> <chr>   <chr>   <chr> <lgl> 
      1     1 A       B       AB    TRUE  
      2     2 B       E       BE    FALSE 
      3     3 C       D       CD    FALSE 
      4     4 D       A       AD    TRUE  
      5     5 A       C       AC    FALSE 
      6     6 B       A       AB    TRUE  
      7     7 A       D       AD    TRUE  
      8     8 C       A       AC    FALSE 
      

      数据:

      我在数据框中设置了stringsAsFactors = F

      df1 <- data.frame(c(1, 2, 3, 4, 5, 6, 7, 8),
                          c("A", "B", "C", "D", "A", "B", "A", "C"), 
                          c("B", "E", "D", "A", "C", "A", "D", "A"), stringsAsFactors = F)
      colnames(df1) <- c("ID", "Number1", "Number2")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-29
        相关资源
        最近更新 更多