left join + anti join 在 R 中的用法

huangapple go评论89阅读模式
英文:

left join + anti join in R

问题

有没有一种方法可以执行left_join,排除匹配项?

  1. A <- sample(1:100, 10)
  2. B <- sample(1:100, 10)
  3. C <- sample(1:100, 10)
  4. year <- sample(1000:2000, 10)
  5. x <- tibble(year, A, B) %>%
  6. mutate(B = B * 12)
  7. y <- tibble(year, B, C)

我想要的是 x + 来自 y 的列,这些列不在 x 中

编辑:所有数据集的年份都相同,但我已经对 x 中的 B 列进行了转换,使其不再与集合 y 中的列匹配。

我希望最终得到一个框架:x(year, A, B, C),其中的 B 是最初在 x 中的 B 列。

我尝试过使用 coalesce(x, y),但没有成功,有人有关于这个的线索吗?
我是不是在尝试做一些非常愚蠢的事情或者漏掉了一些细节?

我知道我可以简单地从 y 中删除我不想要的列,或者只需通过= "year" 进行连接,然后删除带有 .y 后缀的列,但希望有一种更好的方法来实现这一点!

英文:

Is there a way to perform a left_join that excludes matches?

  1. A&lt;-sample(1:100, 10)
  2. B&lt;-sample(1:100, 10)
  3. C&lt;-sample(1:100, 10)
  4. year&lt;-sample(1000:2000,10)
  5. x&lt;-tibble(year,A,B)%&gt;%
  6. mutate(B=B*12)
  7. y&lt;-tibble(year,B,C)

I want x + the cols from y that are not in x

EDIT: Year is the same across all the datasets, but I have transformed the B column in x so that it no longer matches the one in set y.

I want to finish with a frame: x(year,A,B,C) where the B is the one that was in x originally.

I tried with coalesce(x,y) but to no avail, anyone have any clues about this?
Am I trying to do something really stupid or missing some detail?

I know that I could just drop the columns I don''t want from y, or that I could just join by = "year" and then drop the ones with the .y suffix, but hoping that there a nicer way to accomplish this!

答案1

得分: 2

如果我理解正确,一个潜在的解决方案是使用powerjoin包执行power_left_join(),如果存在冲突则从x中进行选择,例如:

  1. library(tidyverse)
  2. # install.packages("powerjoin")
  3. library(powerjoin)
  4. set.seed(42)
  5. A <- sample(1:100, 10)
  6. B <- sample(1:100, 10)
  7. C <- sample(1:100, 10)
  8. year <- sample(1000:2000, 10)
  9. y <- tibble(year, B, C)
  10. x <- tibble(year, A, B)
  11. # 修改"x"中的第一个"B"值
  12. x$B[1] <- 1000
  13. x %>%
  14. power_left_join(y, by = "year", conflict = ~.x)
  15. #> # A tibble: 10 × 4
  16. #> year A C B
  17. #> <int> <int> <int> <dbl>
  18. #> 1 1313 49 34 1000
  19. #> 2 1647 65 92 20
  20. #> 3 1291 25 3 26
  21. #> 4 1835 74 58 3
  22. #> 5 1981 18 42 41
  23. #> 6 1145 100 24 89
  24. #> 7 1620 47 30 27
  25. #> 8 1347 24 43 36
  26. #> 9 1196 71 15 5
  27. #> 10 1515 89 22 84

然而,另一种方法是放弃“.y”列并将“.x”列重命名,这并不更加“困难”(这是我个人使用的方法)。

  1. x %>%
  2. left_join(y, by = "year") %>%
  3. select(-ends_with(".y")) %>%
  4. rename_with(~gsub(".x", "", .x))
  5. #> # A tibble: 10 × 4
  6. #> year A B C
  7. #> <int> <int> <dbl> <int>
  8. #> 1 1313 49 1000 34
  9. #> 2 1647 65 20 92
  10. #> 3 1291 25 26 3
  11. #> 4 1835 74 3 58
  12. #> 5 1981 18 41 42
  13. #> 6 1145 100 89 24
  14. #> 7 1620 47 27 30
  15. #> 8 1347 24 36 43
  16. #> 9 1196 71 5 15
  17. #> 10 1515 89 84 22

在2023-07-06使用reprex v2.0.2创建

英文:

If I've understood correctly, one potential solution is to use the powerjoin package to do a power_left_join() and 'select' the value from x if there are any conflicts, e.g.

  1. library(tidyverse)
  2. # install.packages(&quot;powerjoin&quot;)
  3. library(powerjoin)
  4. set.seed(42)
  5. A &lt;- sample(1:100, 10)
  6. B &lt;- sample(1:100, 10)
  7. C &lt;- sample(1:100, 10)
  8. year &lt;- sample(1000:2000, 10)
  9. y &lt;- tibble(year, B, C)
  10. x &lt;- tibble(year, A, B)
  11. # change the first &quot;B&quot; value in &quot;x&quot;
  12. x$B[1] &lt;- 1000
  13. x %&gt;%
  14. power_left_join(y, by = &quot;year&quot;, conflict = ~.x)
  15. #&gt; # A tibble: 10 &#215; 4
  16. #&gt; year A C B
  17. #&gt; &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;dbl&gt;
  18. #&gt; 1 1313 49 34 1000
  19. #&gt; 2 1647 65 92 20
  20. #&gt; 3 1291 25 3 26
  21. #&gt; 4 1835 74 58 3
  22. #&gt; 5 1981 18 42 41
  23. #&gt; 6 1145 100 24 89
  24. #&gt; 7 1620 47 30 27
  25. #&gt; 8 1347 24 43 36
  26. #&gt; 9 1196 71 15 5
  27. #&gt; 10 1515 89 22 84

However, the alternative approach of dropping the ".y" columns and renaming the ".x" columns isn't that much 'harder' (this is what I personally use).

  1. x %&gt;%
  2. left_join(y, by = &quot;year&quot;) %&gt;%
  3. select(-ends_with(&quot;.y&quot;)) %&gt;%
  4. rename_with(~gsub(&quot;.x&quot;, &quot;&quot;, .x))
  5. #&gt; # A tibble: 10 &#215; 4
  6. #&gt; year A B C
  7. #&gt; &lt;int&gt; &lt;int&gt; &lt;dbl&gt; &lt;int&gt;
  8. #&gt; 1 1313 49 1000 34
  9. #&gt; 2 1647 65 20 92
  10. #&gt; 3 1291 25 26 3
  11. #&gt; 4 1835 74 3 58
  12. #&gt; 5 1981 18 41 42
  13. #&gt; 6 1145 100 89 24
  14. #&gt; 7 1620 47 27 30
  15. #&gt; 8 1347 24 36 43
  16. #&gt; 9 1196 71 5 15
  17. #&gt; 10 1515 89 84 22

<sup>Created on 2023-07-06 with reprex v2.0.2</sup>

答案2

得分: 1

我们可以使用 setdiff 识别新列名(我使用 base::setdiff 来避免可能的冲突,如果有人加载了 lubridate)。然后使用年份和来自 y 的这些列进行连接。

  1. new_cols <- base::setdiff(colnames(y), colnames(x))
  2. left_join(x, y[,c("year", new_cols)])

连接依据为 by = join_by(year)

英文:

We could identify the new column names with setdiff (I'm using base::setdiff to avoid the potential conflict if someone has loaded lubridate.), and then join using year + those columns from y.

  1. new_cols &lt;- base::setdiff(colnames(y), colnames(x))
  2. left_join(x, y[,c(&quot;year&quot;, new_cols)])
  3. Joining with `by = join_by(year)`
  4. # A tibble: 10 &#215; 4
  5. year A B C
  6. &lt;int&gt; &lt;int&gt; &lt;int&gt; &lt;int&gt;
  7. 1 1336 8 100 66
  8. 2 1643 1 57 76
  9. 3 1896 58 24 15
  10. 4 1965 65 66 69
  11. 5 1361 74 18 43
  12. 6 1526 92 38 78
  13. 7 1870 36 8 68
  14. 8 1151 15 86 92
  15. 9 1748 35 16 19
  16. 10 1624 82 30 42

huangapple
  • 本文由 发表于 2023年7月6日 11:01:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76625220.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定