从 R 中的双单关系数据框中推导出第 3 方亲属关系

帕科

我有一张表显示双单亲缘关系。换句话说,我可能有第一行显示有儿子的父亲的记录,在下一行,这个儿子显示他与父亲的关系。但是,父亲可能有另一个儿子(son2),所以我们在表中还有两个条目显示父亲与他的儿子 2 相关,而儿子 2 与共同的父亲相关联。当两个儿子之间的关系没有出现在表中时,问题就出现了。没有条目显示son1 是son2 的兄弟,我需要从表中得出这一点。这是我的目标,表格中的每个人都有一个唯一的标识符。

到目前为止我一直在尝试做的是:

a) 创建所有可能的亲属关系角色的列表(在我上面的简化示例中,只有 2 个角色:父亲和儿子)。

b) 将原始表分成与角色一样多的组。由于我的示例中的任何个人都可能是儿子和/或父亲,因此我创建了两组数据。这些组是列表的元素,因此,换句话说,我通过对记录的角色进行子集化来创建列表。在这个例子中,列表有两个元素:一个用于记录第二个人是第一个人的儿子的记录,另一个元素显示第二个人是第一个人的父亲的条目。

c) 我的想法也是通过第一个人的 ID 对列表的前(两个)元素进行子集化。这样,我的目标是创建每个给定 ID 的组,以及它们拥有的所有关系。例如,在我们的示例中,我们将获得由两行组成的一个 ID(父亲)的组:son1 和son2 的记录。

d) 到这里后,前一个子组显示son1 和son2 是兄弟。同样,这在原始表中没有报告,我的目的是通过编码在原始表中创建两个新记录来导出它,这将显示son1有一个兄弟son2,而son2有一个兄弟son1。

鉴于我的数据框是 df 并且关系中第二个人的变量角色是 Role_2nd,步骤 a) 很简单:

role <- unique(df$Role_2nd)

步骤 b) 也很简单:

newRoles <- lapply(role, function(x){subset(df, Role_2nd == x)})

在步骤 c) 之后,列表中第一个元素的结果 - 我将 role="son" 子集化的那个 - 可能是这样的:

ID_First  ID_Second    Role_1st      Role_2nd
569         571          father        son
590         592          father        son
587         597          father        son
597         596          father        son
597         598          father        son
603         604          father        son
603         607          father        son 

我们可以看到,ID 597 有两个儿子(596 和 598)。这意味着 596 和 598 是兄弟姐妹,我需要推导出原始表中不存在的这种关系。

在步骤 d) 之后,并按 ID 进行子集化:

ID_First  ID_Second    Role_1st      Role_2nd
569         571          father        son

ID_First  ID_Second    Role_1st      Role_2nd
590         592          father        son

ID_First  ID_Second    Role_1st      Role_2nd
587         597          father        son

ID_First  ID_Second    Role_1st      Role_2nd
597         596          father        son
597         598          father        son

ID_First  ID_Second    Role_1st      Role_2nd
603         604          father        son
603         607          father        son 

(可能,步骤 d)对于我的最终目标是可有可无的)。

按照这个例子,列表的另一个元素 - 父亲作为 Role_2nd 的元素 - 应该是这样的:

Step c)

ID_First   ID_Second       Role_1st       Role_2nd
571          569              son          father
592          590              son          father
597          587              son          father
596          597              son          father
598          597              son          father
604          603              son          father
607          603              son          father


I skip showing step d) also for the second element.

现在,这就是我所坚持的。如果以上所有内容都是正确的 - 可能有更简单的方法来解决这个问题 - 考虑到我想创建原始表中不存在的角色“兄弟”,我的想法是通过一个运行列表的两个元素环形。从第一个开始,每当我发现重复的 ID_First(发生在 597 和 603 中)时,这意味着他们所关联的两个人(一方面是 -596 和 598,另一方面是 604 和607-) 必须是“兄弟”。

但我不知道如何做到这一点。我不知道如何在列表的一个元素中发现一个变量的几个相等的值(比如在列表的第一个元素中发现两个或多个相等的 ID_First);我不知道如何对它们进行子集化;我不知道如何为列表的每个元素的每个组件运行循环;我也不知道如何以更简单的方式编写代码而不是运行无限循环(这里我只展示了两个不同的角色,但在我的案例中角色的数量非常大 - 因为我正在工作与“非西方”亲属关系-)。

总结一下,我的问题的最终结果是这样的:

ID_First   ID_Second       Role_1st       Role_2nd
596          597              son          father
598          597              son          father
596          598            brother        brother
598          596            brother        brother
604          603              son          father
607          603              son          father
604          607            brother        brother
607          604            brother        brother

如果有人可以提供任何提示,他们将非常受欢迎。

太感谢了!

完美的

考虑使用关系数据库,通过集成的Families关系正确规范您的关系其中您想要的结果只是Persons自联接查询

具体来说,在关系数据库(如 SQLite(免费、开源、文件级))中,FamiliesPersons之间创建以下一对多关系,每个关系都在粒度级别,R 可以使用 RSQLite 连接到该关系数据库。Persons 中的角色下面是在整个家庭的背景下的绝对(非相对)角色,例如被识别祖父

CREATE TABLE Families (
  ID INTEGER,
  FAMILY_NAME VARCHAR(50)
);

CREATE TABLE Persons (
  ID INTEGER,
  FAM_ID INTEGER,
  Role VARCHAR(50),
  FOREIGN KEY(FAM_ID) REFERENCES Family(ID)  
);


INSERT INTO Families
VALUES (1, 'Alpha'), (2, 'Bravo'), (3, 'Charlie'), (4, 'Delta');

INSERT INTO Persons
VALUES(569, 1, 'father'),
      (590, 2, 'father'),
      (587, 3, 'grandfather'),
      (597, 3, 'father'),
      (603, 4, 'father'),
      (571, 1, 'son'),
      (592, 2, 'son'),
      (597, 3, 'son'),
      (596, 3, 'son'),
      (598, 3, 'son'),
      (604, 4, 'son'),
      (607, 4, 'son');

然后使用条件逻辑运行以下查询来分配兄弟

SELECT p1.ID AS ID1, p2.ID AS ID2,
       CASE 
            WHEN p1.Role = 'son' AND p2.Role = 'son'
            THEN 'brother'
            ELSE p1.Role
       END As Role1,

       CASE 
            WHEN p1.Role = 'son' AND p2.Role = 'son'
            THEN 'brother'
            ELSE p2.Role
       END As Role2

FROM Persons p1
INNER JOIN Persons p2 ON p1.FAM_ID = p2.FAM_ID AND p1.ID > p2.ID

ORDER BY p1.ID, p2.ID;

-- | ID1 | ID2 | Role1   | Role2       |
-- | --- | --- | ------- | ----------- |
-- | 571 | 569 | son     | father      |
-- | 592 | 590 | son     | father      |
-- | 596 | 587 | son     | grandfather |
-- | 597 | 587 | father  | grandfather |
-- | 597 | 587 | son     | grandfather |
-- | 597 | 596 | father  | son         |
-- | 597 | 596 | brother | brother     |
-- | 598 | 587 | son     | grandfather |
-- | 598 | 596 | brother | brother     |
-- | 598 | 597 | son     | father      |
-- | 598 | 597 | brother | brother     |
-- | 604 | 603 | son     | father      |
-- | 607 | 603 | son     | father      |
-- | 607 | 604 | brother | brother     |

在 DB Fiddle 上查看 (一定要单击运行以获得结果)


如果您想完全留在 R 中,请考虑构建这样对应的FamiliesPersons数据框并运行相同的合并和条件逻辑:

建造

Families <- data.frame(ID = seq(1, 4),
                       Family_Name = c("Alpha", "Bravo", "Charlie", "Delta"))

Persons <- data.frame(ID = c(569, 590, 587, 597, 603, 571, 592, 597, 596, 598, 604, 607),
                      Fam_ID = c(1, 2, 3, 3, 4, 1, 2, 3, 3, 3, 4, 4),
                      Role = c("father", "father", "grandfather", "father", "father",
                               "son", "son", "son", "son", "son", "son", "son"))

询问

# SELF JOIN, AVOIDING REVERSE DUPLICATES
merge_raw <- subset(merge(Persons, Persons, by="Fam_ID", suffixes = c("_1", "_2")), 
                    ID_1 > ID_2) 

# CONDITIONALLY ASSIGN "brother"
final_df <- within(merge_raw, {    
        ID_1 <- ifelse(ID_1 == "son" & ID_2 == "son", "brother", ID_1)
        ID_2 <- ifelse(ID_1 == "son" & ID_2 == "son", "brother", ID_2)
    })

# RE-ORDER ROWS AND COLUMNS
final_df <- with(final_df, data.frame(final_df[order(ID_1, ID_2), 
                                               c("ID_1", "ID_2", "Role_1", "Role_2")],
                                      row.names = NULL))

final_df

#    ID_1 ID_2 Role_1      Role_2
# 1   571  569    son      father
# 2   592  590    son      father
# 3   596  587    son grandfather
# 4   597  587 father grandfather
# 5   597  587    son grandfather
# 6   597  596 father         son
# 7   597  596    son         son
# 8   598  587    son grandfather
# 9   598  596    son         son
# 10  598  597    son      father
# 11  598  597    son         son
# 12  604  603    son      father
# 13  607  603    son      father
# 14  607  604    son         son

查看雷克斯特

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章