cross-join 用于从同一 R 数据框中的其他列中提取数据的 ID
cross-join ids to extract data from other columns within the same R data frame
我有一个像这样的 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
Children和parents关系是通过不同的ID建立的。
对于没有 marriage 日期值的每个人 (id),我想估计该列的日期值,基于Birth_date of his/her first child(当然这只是一个假设,因为对于一些人 Birth_Date 不可用。
因此,在这个例子中,一些获得 婚姻 日期的个人将是 I0002 和 I0003(计算得出的 婚姻 将是“ 1971-06-02" 在第 3 行和第 4 行,因为它是具有 Father_id[= 的 3 个人中最小的 Birth_Date 55=]=='I0002' 和 Mother_id=='I0003' - 第 2、5 和 9 行)。
同理,I0005 和 I0006 的结婚日期为“1936-10-05”,这是最小的 已知 Birth_Date 的 children (I0002, I0007 和 I0009 - NA 作为 Birth_Date-)。 但是在这种情况下,所有children Birth_Date值不应该被考虑在内,因为数据框已经这些个体的真实 marriage_date 值(“1936-10-27”)。
如您所见,数据帧结构没有改变(相同的行数和相同的列;但最后一个用日期值更新了一些 NA)。
预期结果:
> 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
是否可以避免使用函数迭代数据框来完成此任务?
我知道有处理连接的库,就像提到的那些 here。但我仍然无法弄清楚如何使用它们来完成这项任务。
我想逐行计算(每次迭代计算一个结婚日期),但我想一定有一些更快的方法可以做到这一点。
请详细说明你的答案,因为我是一个完整的 R-newbie。这不仅仅是让它发挥作用的问题,而是理解它是如何工作的问题。
我们可以 select 每个父亲和母亲的最小值为 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
我有一个像这样的 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
Children和parents关系是通过不同的ID建立的。
对于没有 marriage 日期值的每个人 (id),我想估计该列的日期值,基于Birth_date of his/her first child(当然这只是一个假设,因为对于一些人 Birth_Date 不可用。
因此,在这个例子中,一些获得 婚姻 日期的个人将是 I0002 和 I0003(计算得出的 婚姻 将是“ 1971-06-02" 在第 3 行和第 4 行,因为它是具有 Father_id[= 的 3 个人中最小的 Birth_Date 55=]=='I0002' 和 Mother_id=='I0003' - 第 2、5 和 9 行)。
同理,I0005 和 I0006 的结婚日期为“1936-10-05”,这是最小的 已知 Birth_Date 的 children (I0002, I0007 和 I0009 - NA 作为 Birth_Date-)。 但是在这种情况下,所有children Birth_Date值不应该被考虑在内,因为数据框已经这些个体的真实 marriage_date 值(“1936-10-27”)。
如您所见,数据帧结构没有改变(相同的行数和相同的列;但最后一个用日期值更新了一些 NA)。
预期结果:
> 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
是否可以避免使用函数迭代数据框来完成此任务?
我知道有处理连接的库,就像提到的那些 here。但我仍然无法弄清楚如何使用它们来完成这项任务。
我想逐行计算(每次迭代计算一个结婚日期),但我想一定有一些更快的方法可以做到这一点。 请详细说明你的答案,因为我是一个完整的 R-newbie。这不仅仅是让它发挥作用的问题,而是理解它是如何工作的问题。
我们可以 select 每个父亲和母亲的最小值为 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