идентификаторы перекрестного соединения для извлечения данных из других столбцов в том же фрейме данных R - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть такой фрейм данных R (но данные не сортируются ни по одному столбцу):

ppl <- structure(list(id = c("I0000", "I0001", "I0002", "I0003", "I0004","I0005", "I0006", "I0007", "I0008", "I0009"), Birth_Date = structure(c(NA, 517, -10246, -8723, 2349, -25125, NA, -12141, 2349, NA), class = "Date"), Father_id = c(NA, "I0002", "I0005", "I0037", "I0002", "I0018", "I0056", "I0005", "I0002", "I0005"), Mother_id = c(NA, "I0003", "I0006", "I0038", "I0003", "I0019", "I0057", "I0006", "I0003", "I0006"), marriage = structure(c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, -12119, -12119, NA_real_, NA_real_, NA_real_), class = "Date")), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))

> ppl
# A tibble: 10 x 5
   id    Birth_Date Father_id Mother_id marriage  
   <chr> <date>     <chr>     <chr>     <date>    
 1 I0000 NA         NA        NA        NA        
 2 I0001 1971-06-02 I0002     I0003     NA        
 3 I0002 1941-12-13 I0005     I0006     NA        
 4 I0003 1946-02-13 I0037     I0038     NA        
 5 I0004 1976-06-07 I0002     I0003     NA        
 6 I0005 1901-03-19 I0018     I0019     1936-10-27        
 7 I0006 NA         I0056     I0057     1936-10-27        
 8 I0007 1936-10-05 I0005     I0006     NA        
 9 I0008 1976-06-07 I0002     I0003     NA        
10 I0009 NA         I0005     I0006     NA    

Отношения между детьми и родителями устанавливаются через их разные идентификаторы.

Для каждого человека ( id ) без значения даты брак я хочу оценить значение даты для этого столбца на основе Дата рождения его / ее первого ребенка (конечно, это всего лишь предположение, поскольку для некоторых людей Дата рождения недоступна).

Итак, в этом примере некоторые лица, которые получили бы брак дату, были бы I0002 и I0003 (вычисленные брак были бы "1971-06-02" в строках 3 и 4, потому что это минимальная дата рождения из 3 человек, у которых Father_id == 'I0002' и Mother_id == 'I0003' - строки 2, 5 и 9-).

Точно так же, индивиды I0005 и I0006 получат дату брака "1936-10-05", которая является минимальной известной Дата рождения их детей (I0002, I0007 и I0009 - у которых NA как Дата рождения -). Но в этом случае все дочерние значения Birth_Date не должны приниматься во внимание, потому что фрейм данных уже имеет действительное значение wedding_date для этих лиц ("1936- 10-27 ").

Как видите, структура фрейма данных не должна изменяться (такое же количество строк и одинаковых столбцов; но последний получает несколько NA, обновленных значением Date).

Ожидаемый результат:

> ppl
# A tibble: 10 x 5
   id    Birth_Date Father_id Mother_id marriage  
   <chr> <date>     <chr>     <chr>     <date>    
 1 I0000 NA         NA        NA        NA        
 2 I0001 1971-06-02 I0002     I0003     NA        
 3 I0002 1941-12-13 I0005     I0006     1971-06-02
 4 I0003 1946-02-13 I0037     I0038     1971-06-02
 5 I0004 1976-06-07 I0002     I0003     NA        
 6 I0005 1901-03-19 I0018     I0019     1936-10-27
 7 I0006 NA         I0056     I0057     1936-10-27
 8 I0007 1936-10-05 I0005     I0006     NA        
 9 I0008 1976-06-07 I0002     I0003     NA        
10 I0009 NA         I0005     I0006     NA        

Можно ли выполнить sh эту задачу, избегая функции для итерации фрейма данных?

Я знаю, что есть библиотеки, имеющие дело с объединениями, подобные упомянутым здесь . Но я все еще не могу понять, как использовать их для выполнения этой задачи.

Я думал вычислять это построчно (одна дата брака на итерацию), но я думаю, что должны быть более быстрые способы сделать это. Пожалуйста, опишите немного ваш ответ, потому что я полный R-newb ie. Дело не просто в том, чтобы заставить его работать, а в том, чтобы понять, как оно работает.

1 Ответ

1 голос
/ 11 апреля 2020

Мы можем выбрать строку с минимальным значением Birth_Date для каждого отца и матери и присоединиться к самому фрейму данных.

library(dplyr)

ppl %>%
   #Keep only NA values
   filter(is.na(marriage)) %>%
   #For each father and mother
   group_by(Father_id, Mother_id) %>%
   #Select the minimum date
   slice(which.min(Birth_Date)) %>%
   #Get father and mother in same column
   tidyr::pivot_longer(cols = c(Father_id, Mother_id)) %>%
   #rename Birth_Date to marriage and select it with value
   select(marriage = Birth_Date, value) %>%
   #Join with the dataframe itself
   right_join(ppl, by = c('value' = 'id')) %>%
   #If marriage data is already present select that
   mutate(marriage_date = coalesce(marriage.y, marriage.x)) %>%
   #select only columns needed. 
   select(id = value, Birth_Date, Father_id, Mother_id, marriage_date)

   id    Birth_Date Father_id Mother_id marriage_date
   <chr> <date>     <chr>     <chr>     <date>       
 1 I0000 NA         NA        NA        NA           
 2 I0001 1971-06-02 I0002     I0003     NA           
 3 I0002 1941-12-13 I0005     I0006     1971-06-02   
 4 I0003 1946-02-13 I0037     I0038     1971-06-02   
 5 I0004 1976-06-07 I0002     I0003     NA           
 6 I0005 1901-03-19 I0018     I0019     1936-10-27   
 7 I0006 NA         I0056     I0057     1936-10-27   
 8 I0007 1936-10-05 I0005     I0006     NA           
 9 I0008 1976-06-07 I0002     I0003     NA           
10 I0009 NA         I0005     I0006     NA   
...