【问题标题】:Match with multiple criteria without loop in R在R中匹配多个没有循环的条件
【发布时间】:2018-05-04 09:47:21
【问题描述】:

我有一个显示一组条件的数据框,例如:

B = data.frame(col1 = 1:10, col2 = 11:20 )

例如,第一行表示当 col1 = 1 时,col2 = 11。 我还有另一个数据框,其中的数字应满足这些条件,例如:

A = data.frame(col1 = c(1:11,1:11), col2 = c(11:21,11:21), col3 = 101:122)

我想返回矩阵 A 中满足 B 中条件的所有行的 col3 中的值的总和。例如,使用 B 中的第一行,该值是:

sum(A$col3[which(A$col1 == B$col1[1] & A$col2 == B$col2[1])])
#[1] 213

这是A 的第 1 行和第 12 行中 col3 中条目的总和。我需要为矩阵A 的所有行找到一个包含所有这些总和的向量。我知道如何使用循环来执行此操作,但是在我的数据矩阵中 AB 非常大并且有很多条件,所以我想知道是否有办法在没有循环的情况下做同样的事情。谢谢。

【问题讨论】:

  • 我稍微编辑了您的原始帖子,因为您在 R 中称为 matrix 实际上是 data frame

标签: r loops dataframe conditional match


【解决方案1】:

基础 R 中的解决方案

# Sum identical rows
A.summed <- aggregate(col3 ~ col1 + col2, data = A, sum);

# Select col1 col2 combinations that are also present in B 
A.summed.sub <- subset(A.summed, paste(col1, col2) %in% paste(B$col1, B$col2));
#   col1 col2 col3
#1     1   11  213
#2     2   12  215
#3     3   13  217
#4     4   14  219
#5     5   15  221
#6     6   16  223
#7     7   17  225
#8     8   18  227
#9     9   19  229
#10   10   20  231

或者和单线一样

A.summed.sub <- subset(aggregate(col3 ~ col1 + col2, data = A, sum), paste(col1, col2) %in% paste(B$col1, B$col2));

# Add summed col3 to dataframe B by matching col1 col2 combinations
B$col3 <- A.summed[match(paste(B$col1, B$col2), paste(A.summed$col1, A.summed$col2)), "col3"];
B;
#   col1 col2 col3
#1     1   11  213
#2     2   12  215
#3     3   13  217
#4     4   14  219
#5     5   15  221
#6     6   16  223
#7     7   17  225
#8     8   18  227
#9     9   19  229
#10   10   20  231

【讨论】:

  • 这是一个非常简单的解决方案。有没有办法通过添加列 (col3) 而不是创建新矩阵来填充矩阵 B,以便 B 中不匹配的行得到 0?
  • 不完全确定您的意思。请看看我修改后的解决方案。
【解决方案2】:

使用dplyr 的解决方案。 A2 是最终输出。这个想法是将col1col2 中的值分组并计算col3 的总和。 semi_join是根据col1col2中的B匹配值来过滤数据框。

library(dplyr)

A2 <- A %>%
  group_by(col1, col2) %>%
  summarise(col3 = sum(col3)) %>%
  semi_join(B, by = c("col1", "col2")) %>%
  ungroup()
A2
# # A tibble: 10 x 3
#     col1  col2  col3
#    <int> <int> <int>
#  1     1    11   213
#  2     2    12   215
#  3     3    13   217
#  4     4    14   219
#  5     5    15   221
#  6     6    16   223
#  7     7    17   225
#  8     8    18   227
#  9     9    19   229
# 10    10    20   231

【讨论】:

    【解决方案3】:

    我们可以使用data.table 加入on

    library(data.table(
    setDT(A)[B, .(col3 = sum(col3)), on = .(col1, col2), by = .EACHI]
    #    col1 col2 col3
    # 1:    1   11  213
    # 2:    2   12  215
    # 3:    3   13  217
    # 4:    4   14  219
    # 5:    5   15  221
    # 6:    6   16  223
    # 7:    7   17  225
    # 8:    8   18  227
    # 9:    9   19  229
    #10:   10   20  231
    

    【讨论】:

      猜你喜欢
      • 2021-05-14
      • 2016-02-23
      • 1970-01-01
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 2022-12-18
      • 2022-08-13
      • 1970-01-01
      相关资源
      最近更新 更多