Соответствующие пары, встречающиеся в нескольких строках - PullRequest
0 голосов
/ 22 декабря 2018

Я моделирую популяцию птиц мужского и женского пола, а самки выбирают партнера для размножения.Население - это фрейм данных, и каждая строка представляет собой уникального индивида, его 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 голосов
/ 22 декабря 2018

Решение, которое использует 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)
0 голосов
/ 23 декабря 2018

Вот два решения, которые оба используют self join :

1.dplyr

Это несколько улучшенная версия ответа PoGibas , в котором 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
0 голосов
/ 22 декабря 2018

Вот один из возможных подходов:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...