根据来自另一个数据框的多个列向数据框添加新列

时间:2020-09-01 12:43:01

标签: r merge match left-join mutate

我从两个数据框中获得了信息:df1包含有关个人的信息,df2包含有关这些个人的父母的信息。

> df1
      ID  Obs   sire    dam
1 313425 Obs1 241600 238895
2 313425 Obs2 241600 238895
3 313425 Obs3 241600 238895
4 313531 Obs2 239742 241447
5 315760 Obs2 238355 236642
6 315760 Obs1 238355 236642

> df2
   Animal  Obs Obs_value
1  241600 Obs1      19.9
2  239742 Obs1      19.6
3  238355 Obs1      18.5
4  238895 Obs1      20.1
5  241447 Obs1      22.0
6  236642 Obs1      19.8
7  241600 Obs2       1.9
8  239742 Obs2       1.6
9  238355 Obs2       1.5
10 238895 Obs2       2.1
11 241447 Obs2       2.0
12 236642 Obs2       1.8
13 241600 Obs3         1
14 239742 Obs3         1
15 238355 Obs3         1
16 238895 Obs3         1
17 241447 Obs3         0
18 236642 Obs3         1

我想将df2中的信息添加到df1中,在这里我想将df1 $ Obs,df1 $ sire(或df1 $ dam)列与df2 $ Animal,df2 $ Obs匹配并将df2 $ Obs_value返回到df1中。 所需输出示例:

> df1
      ID  Obs   sire    dam sire_value dam_value
1 313425 Obs1 241600 238895       19.9      20.1
2 313425 Obs2 241600 238895        1.9       1.5
3 313425 Obs3 241600 238895          1         1
4 313531 Obs2 239742 241447        1.6       2.0
5 315760 Obs2 238355 236642        1.5       1.8
6 315760 Obs1 238355 236642          1      19.8

我尝试了以下代码,但这并没有给出正确的结果(或根本没有给出任何结果)。

> df1 <- df1 %>% mutate(sire_value = left_join(df1, df2, by.x = c("ID", "Obs"), by.y = c("Animal", "Obs")))
Joining, by = "Obs"
Error: Problem with `mutate()` input `sire_value`.
x Input `sire_value` can't be recycled to size 6.
i Input `sire_value` is `left_join(...)`.
i Input `sire_value` must be size 6 or 1, not 36.
Run `rlang::last_error()` to see where the error occurred.

有人可以帮我吗?非常感谢!

2 个答案:

答案 0 :(得分:4)

一个通用/可扩展的解决方案是获取长格式的数据,将数据加入并以宽格式返回:

library(dplyr)
library(tidyr)

df1 %>%
  pivot_longer(cols = c(sire, dam)) %>%
  left_join(df2, by = c('Obs', 'value' = 'Animal')) %>%
  pivot_wider(names_from = name, values_from = c(Obs_value, value))

#     ID Obs   Obs_value_sire Obs_value_dam value_sire value_dam
#   <int> <chr>          <dbl>         <dbl>      <int>     <int>
#1 313425 Obs1            19.9          20.1     241600    238895
#2 313425 Obs2             1.9           2.1     241600    238895
#3 313425 Obs3             1             1       241600    238895
#4 313531 Obs2             1.6           2       239742    241447
#5 315760 Obs2             1.5           1.8     238355    236642
#6 315760 Obs1            18.5          19.8     238355    236642

如果像本例中那样只有两列要联接,则可以将它们分别联接。

df1 %>%  
  left_join(df2 %>% rename(sire_value = Obs_value), 
                     by = c('Obs', 'sire' = 'Animal')) %>%
  left_join(df1 %>%  left_join(df2 %>% rename(dam_value = Obs_value), 
                     by = c('Obs', 'dam' = 'Animal')))

答案 1 :(得分:2)

我可以使用 data.table 包解决您的问题。使用 data.table 处理数据框架或数据表非常有效,因此您以后可能要使用它。

{{1}}

让我们知道您的问题是否已解决。