多行中出现的匹配对

时间:2018-12-22 05:47:30

标签: r tidyverse

我正在模拟雄性和雌性鸟类的种群,雌性选择与之交配的伴侣。人口是一个数据框,每一行都是一个唯一的个体,其ID,其伴侣的ID(如果已配对),性别以及是否已配对。

我正在跟踪谁与谁配对,因此我可以跟踪后代将获得哪些特征。雌雄配对的数据以及在数据框中与谁配对的数据,但是我也想在其中具有相互关系(因此,selfID为D和E的行应分别具有mateID的A和B)。有没有简单的方法可以做到这一点?现在什么都没想到...

df <- structure(list(selfID = c("A", "B", "C", "D", "E"), mateID = c("D", 
"E", NA, NA, NA), sex = c("female", "female", "female", "male", 
"male"), paired = c(TRUE, TRUE, FALSE, NA, NA)), row.names = c(NA, 
-5L), class = c("tbl_df", "tbl", "data.frame"))

selfID mateID sex    paired
  <chr>  <chr>  <chr>  <lgl> 
1 A      D      female TRUE  
2 B      E      female TRUE  
3 C      NA     female FALSE 
4 D      NA     male   NA    
5 E      NA     male   NA 

3 个答案:

答案 0 :(得分:1)

这是一种可能的方法:

for(i in df$mateID[!is.na(df$mateID)]) {
  df$mateID[df$selfID == i] <- df$selfID[df$mateID == i & !is.na(df$mateID)]
}

df$paired[!is.na(df$mateID)] <- T

df
# # A tibble: 5 x 4
# selfID mateID sex    paired
# <chr>  <chr>  <chr>  <lgl> 
# 1 A      D      female TRUE  
# 2 B      E      female TRUE  
# 3 C      <NA>   female FALSE 
# 4 D      A      male   TRUE  
# 5 E      B      male   TRUE

答案 1 :(得分:1)

本身使用merge的解决方案(不执行循环)。

library(dplyr)
merge(df, df, by.x = "selfID", by.y = "mateID", all.x = TRUE) %>%
    mutate(mateID = ifelse(is.na(mateID), selfID.y, mateID),
           paired = ifelse(is.na(paired.x), paired.y, paired.x)) %>%
    select(selfID, sex = sex.x, mateID, paired)

答案 2 :(得分:1)

以下是两个都使用 self join 的解决方案:

1。 dplyr

这是PoGibas' answer的某种修饰版本,它使用left_join()代替merge()coalesce()代替基数R的ifelse()

library(dplyr)
df %>% 
  left_join(df, by = c("selfID" = "mateID")) %>% 
  mutate(mateID = coalesce(mateID, selfID.y), 
         paired = coalesce(paired.x, paired.y)) %>% 
  select(selfID, mateID, sex = sex.x, paired)
# A tibble: 5 x 4
  selfID mateID sex    paired
  <chr>  <chr>  <chr>  <lgl> 
1 A      D      female TRUE  
2 B      E      female TRUE  
3 C      NA     female FALSE 
4 D      A      male   TRUE  
5 E      B      male   TRUE

2。 data.table

为完整起见(并注意问题已用标记),这是一个单行代码,它使用data.table的能力自我执行更新加入

library(data.table)
setDT(df)[df, on = .(selfID = mateID), `:=`(mateID = i.selfID, paired = TRUE)]
df
   selfID mateID    sex paired
1:      A      D female   TRUE
2:      B      E female   TRUE
3:      C   <NA> female  FALSE
4:      D      A   male   TRUE
5:      E      B   male   TRUE