当前位置: 首页 > 知识库问答 >
问题:

R:基于多个条件的合并(具有不相等的标准)

萧霍英
2023-03-14

我想合并基于多个条件的2个数据帧。

DF1 <- data.frame("col1" = rep(c("A","B"), 18),
                  "col2" = rep(c("C","D","E"), 12),
                  "value"= (sample(1:100,36)),
                  "col4" = rep(NA,36))

DF2 <- data.frame("col1" = rep("A",6),
                  "col2" = rep(c("C","D"),3),
                  "data" = rep(c(1,3),3),
                  "min" = seq(0,59,by=10),
                  "max" = seq(10,69,by=10))


> DF1
   col1 col2 value col4
1     A    C    22   NA
2     B    D    58   NA
3     A    E    35   NA
4     B    C    86   NA
5     A    D    37   NA
6     B    E    16   NA
7     A    C    46   NA
8     B    D    23   NA
9     A    E    88   NA
10    B    C     3   NA
11    A    D    33   NA
12    B    E    25   NA
13    A    C    19   NA
14    B    D    24   NA
15    A    E     9   NA
16    B    C    76   NA
17    A    D    62   NA
18    B    E    68   NA
19    A    C    97   NA
20    B    D    43   NA
21    A    E     8   NA
22    B    C    84   NA
23    A    D    36   NA
24    B    E    20   NA
25    A    C    57   NA
26    B    D    99   NA
27    A    E    42   NA
28    B    C    64   NA
29    A    D    87   NA
30    B    E     1   NA
31    A    C    78   NA
32    B    D    34   NA
33    A    E    41   NA
34    B    C    32   NA
35    A    D    10   NA
36    B    E    72   NA

> DF2
  col1 col2 data min max
1    A    C    1   0  10
2    A    D    3  10  20
3    A    C    1  20  30
4    A    D    3  30  40
5    A    C    1  40  50
6    A    D    3  50  60

DF1是主表,DF2被视为查找表

如果DF1的col1和col2与DF2的col1和col2匹配,且DF1的“值”介于DF2的最小值和最大值之间,则DF2的“数据”列将添加到DF1中。如果不满足条件,DF1的“数据”值为NA。

预期输出(前6行):

  col1 col2 value col4 data
1    A    C    22   NA    1
2    B    D    58   NA   NA
3    A    E    35   NA   NA
4    B    C    86   NA   NA
5    A    D    37   NA    3
6    B    E    16   NA   NA

我尝试使用合并(匹配col1和col2)和子集(只过滤值介于最小和最大之间的行),但我的目标是维护DF1的所有行。

有人对此有什么想法吗?

共有3个答案

洪俊拔
2023-03-14

使用包装fuzzyjoin函数的my package safejoin,您可以执行以下操作:

# devtools::install_github("moodymudskipper/safejoin")
library(safejoin)
debugonce(safe_left_join)

safe_left_join(DF1, DF2,  ~
                  X("col1") == Y("col1") & 
                  X("col2") == Y("col2") & 
                  X("value") >= Y("min") &
                  X("value") <= Y("max"),
               conflict = ~.x) %>% 
  head(15)
#    col1 col2 value col4 data min max
# 1     A    C    90   NA   NA  NA  NA
# 2     B    D    20   NA   NA  NA  NA
# 3     A    E     8   NA   NA  NA  NA
# 4     B    C    99   NA   NA  NA  NA
# 5     A    D    42   NA   NA  NA  NA
# 6     B    E    37   NA   NA  NA  NA
# 7     A    C    47   NA    1  40  50
# 8     B    D    61   NA   NA  NA  NA
# 9     A    E    55   NA   NA  NA  NA
# 10    B    C    11   NA   NA  NA  NA
# 11    A    D    81   NA   NA  NA  NA
# 12    B    E    48   NA   NA  NA  NA
# 13    A    C    77   NA   NA  NA  NA
# 14    B    D    58   NA   NA  NA  NA
# 15    A    E     3   NA   NA  NA  NA

此处的conflict参数告诉函数仅返回lhs中的冲突列(col1col2)。

解柏
2023-03-14

您的数据,更改stringsAsFactors=F

DF1 <- data.frame("col1" = rep(c("A","B"), 18),
              "col2" = rep(c("C","D","E"), 12),
              "value"= (sample(1:100,36)),
              "col4" = rep(NA,36),
              stringsAsFactors=F)

DF2 <- data.frame("col1" = rep("A",6),
              "col2" = rep(c("C","D"),3),
              "data" = rep(c(1,3),3),
              "min" = seq(0,59,by=10),
              "max" = seq(10,69,by=10),
              stringsAsFactors=F)

使用dplyr,1)使用left_join合并两个数据,2)检查ifelsevalue是否在minmaxrowwise之间,然后3)取消选择minmax列...

library(dplyr)
left_join(DF1, DF2, by=c("col1","col2")) %>%
  rowwise() %>%
  mutate(data = ifelse(between(value,min,max), data, NA)) %>%
  select(-min, -max)

不确定您是否希望执行某种聚合,但下面是上述代码的输出

    col1  col2 value  col4  data
 1     A     C    23    NA    NA
 2     A     C    23    NA     1
 3     A     C    23    NA    NA
 4     B     D    59    NA    NA
 5     A     E    57    NA    NA
 6     B     C     8    NA    NA
高吉星
2023-03-14

使用最新版本的数据。表,非等联接和联接时更新是可能的:

library(data.table)
head(setDT(DF1)[setDT(DF2), on = c("col1", "col2", "value>=min", "value<=max"), 
                data := data])
   rn col1 col2 value col4 data
1:  1    A    C    22   NA    1
2:  2    B    D    58   NA   NA
3:  3    A    E    35   NA   NA
4:  4    B    C    86   NA   NA
5:  5    A    D    37   NA    3
6:  6    B    E    16   NA   NA
DF1 <- structure(list(rn = 1:36, col1 = c("A", "B", "A", "B", "A", "B", 
"A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", 
"B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", "A", "B", 
"A", "B", "A", "B"), col2 = c("C", "D", "E", "C", "D", "E", "C", 
"D", "E", "C", "D", "E", "C", "D", "E", "C", "D", "E", "C", "D", 
"E", "C", "D", "E", "C", "D", "E", "C", "D", "E", "C", "D", "E", 
"C", "D", "E"), value = c(22L, 58L, 35L, 86L, 37L, 16L, 46L, 
23L, 88L, 3L, 33L, 25L, 19L, 24L, 9L, 76L, 62L, 68L, 97L, 43L, 
8L, 84L, 36L, 20L, 57L, 99L, 42L, 64L, 87L, 1L, 78L, 34L, 41L, 
32L, 10L, 72L), col4 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), .Names = c("rn", 
"col1", "col2", "value", "col4"), row.names = c(NA, -36L), class = "data.frame")
DF2 <- structure(list(rn = 1:6, col1 = c("A", "A", "A", "A", "A", "A"
), col2 = c("C", "D", "C", "D", "C", "D"), data = c(1L, 3L, 1L, 
3L, 1L, 3L), min = c(0L, 10L, 20L, 30L, 40L, 50L), max = c(10L, 
20L, 30L, 40L, 50L, 60L)), .Names = c("rn", "col1", "col2", "data", 
"min", "max"), row.names = c(NA, -6L), class = "data.frame")
 类似资料:
  • 我有一个示例数据集,如下所示 Col1 Col2 Col3 A 1,2,3 A123 A 4,5 A456 A 1,2,3 A456 A 4,5 A123 我参考了一些解决方案,并尝试了以下方法。但它只追加单个列。

  • 我收集了用户在商店购买的物品,以及他从朋友那里得到的喜欢和不喜欢的东西。集合字段如下所示: 现在,我想得到以下总结: 获取用户X的(喜欢-不喜欢)差异 获取用户X的差异(喜欢-不喜欢)到存储Y 获取用户X的(喜欢-不喜欢)差异到商店Y和产品Z 对于#1,我做了: 我得到了正确的结果: [{"_id":"542ea90fbb1e37b09f660980","rankDiff": 2}] 但当我试图通

  • 嗨,我正在寻找一个最快的解决方案来处理csv文件的负载。 情况:我在一个文件夹中有多个csv文件,它们的标题不同 我已经对它们进行了预处理,以删除顶部的垃圾行,因此所有这些都有一个标准标头。 我想将一组CSV文件与完全相同的侦听器合并到一个新文件夹中 示例文件-1。csv 示例文件-2。csv 样本文件-3。csv 样本文件-4。csv 样本文件-5。csv 样品File-6.csv 样本文件-7

  • 问题内容: 我有以下数据集。 https://drive.google.com/drive/folders/1NRelNsXQJ7MTNKcm-T69N6r5ZsOyFmTS?usp=sharing 如果列名称与工作表名称相同,则将所有内容合并在一起作为单独的列,以下是代码 运行以上代码后的数据 merged_data 如何合并条件文件? 健康)状况。 以上代码段中的价格1指向带有名称为int 7

  • 我有数据。看起来像这样的框架 首先,我想根据Day aka group_by(Day)对数据帧进行分组。当在每个组中,每种类型(tr1,tr2)的和(平均sd)大于控制(ctrl)的差(平均sd),然后我想在新列(new.col)中指定值~是,如果不是,我想指定值~否。 例如,我希望我的数据看起来像这样。它不一定要看起来像这样

  • 我尝试在数据帧“df_energy”中添加一个新的列“energy_class”,如果“consumpion_energy”值为 有什么办法可以帮我吗? 先谢谢你