【问题标题】:Add a new column to a dataframe based on multiple columns from another dataframe基于来自另一个数据框的多列向数据框添加新列
【发布时间】:2020-12-20 14:01:01
【问题描述】:

我有来自两个数据框的信息: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.

谁能帮我解决这个问题?非常感谢!

【问题讨论】:

    标签: r merge match left-join dplyr


    【解决方案1】:

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

    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')))
    

    【讨论】:

    • 谢谢!第二个解决方案有效,第一个即使在我重新加载 dplyr 和 tidyr 包之后也找不到函数 pivot_longer()。
    • pivot_longertidyr 的较新版本。我的packageVersion('tidyr') #[1] ‘1.1.2’。用install.packages('tidyr')更新最新版本
    【解决方案2】:

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

    # setup environment
    library('data.table')
    library('dplyr')
    
    # add data table class to df1 and df2
    setDT(df1); setDT(df2)
    # merge data frames on 'sire' column
    df1 = df1[df2, on = .(sire = animal, obs = obs), nomatch = 0L]
    # rename 'value' column name to 'value_sire'
    df1 = df1 %>%
      rename(value_sire = value)
    # merge data frames on 'dam' column
    df1 = df1[df2, on = .(dam = animal, obs = obs), nomatch = 0L]
    # rename new 'value' column to 'value_dam'
    df1 = df1 %>%
      rename(value_dam = value) %>%
      arrange(desc(sire))
    

    如果您的问题已解决,请告诉我们。

    【讨论】:

    • 感谢您的贡献@rodolfoksveiga!我已经使用了@Ronak 的解决方案,但这是另一个同样有效的选项。
    • 实际上,当@Ronak 发布他的答案时,我正在寻找答案……我承认,他更快更优雅!哈哈哈。祝大家好运。
    猜你喜欢
    • 1970-01-01
    • 2022-12-01
    • 2022-07-18
    • 1970-01-01
    • 2018-12-29
    • 2021-05-12
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    相关资源
    最近更新 更多