gpt4 book ai didi

r - 在 R 中生成组(家庭)

转载 作者:行者123 更新时间:2023-12-02 05:37:10 26 4
gpt4 key购买 nike

我有以下类型的数据:

Person <- c("A",  "B", "C",  "D",  "E",  "E",  "F",  "G", "H", "I")
MOM <- c( NA, NA, NA, "A", "A", NA, "A", "B", "C", NA)
DAD <- c( NA, NA, NA, "B", "B", NA, "E", "A", "B", NA)
Xv <- 1:10
myd <- data.frame (Person, MOM, DAD, Xv, stringsAsFactors=F)
myd
Person MOM DAD Xv
1 A <NA> <NA> 1
2 B <NA> <NA> 2
3 C <NA> <NA> 3
4 D A B 4
5 E A B 5
6 E <NA> <NA> 6
7 F A E 7
8 G B A 8
9 H C B 9
10 I <NA> <NA> 10

此数据包括 Person 及其 Mom 和 Dad 列。我想为此数据创建家庭组。 NA 是信息缺失。定义了一个具有共同的 MOM 和 DAD 的家庭。创始人是那些同时拥有 NA、family = 0 的人。

这是我能想到的,但对我来说并不完美:

fun <- function(i) {
i1 <- if (is.na(myd[i, 2])) i else match(myd[i, 2], myd[1:i, 2])
i2 <- if (is.na(myd[i, 3])) i else match(myd[i, 3], myd[1:i, 3])
min(i1, i2)
}
myd$family <- as.numeric(factor(sapply(1:nrow(myd), fun)))
Person MOM DAD Xv family
1 A <NA> <NA> 1 1
2 B <NA> <NA> 2 2
3 C <NA> <NA> 3 3
4 D A B 4 4
5 E A B 5 4
6 E <NA> <NA> 6 5
7 F A E 7 4
8 G B A 8 6
9 H C B 9 4
10 I <NA> <NA> 10 7

上述功能在某种意义上是不完善的:家庭数据不包括 parent 的数据,例如家庭4应该包括A 和 B 的数据。因此完整的家庭看起来像:

1       A <NA> <NA>  1      1
2 B <NA> <NA> 2 2
4 D A B 4 4
5 E A B 5 4

另一件事(至少对我来说是这样),DAD = A 和 MOM = B 与 DAD = B 和 MOM = A 相同。因此,家庭 4 和 6 是同一个 parent A 和 B 的产物,所以应该相同的。

4       D    A    B  4      4
5 E A B 5 4
8 G B A 8 6

因此预期的输出是:

Person  MOM  DAD Xv     family
# founders
1 A <NA> <NA> 1 0
2 B <NA> <NA> 2 0
3 C <NA> <NA> 3 0
10 I <NA> <NA> 10 0
6 E <NA> <NA> 6 0
# Family 1
1 A <NA> <NA> 1 1
2 B <NA> <NA> 2 1
4 D A B 4 1
5 E A B 5 1
8 G B A 8 1
# Family 2
1 A <NA> <NA> 1 2
6 E <NA> <NA> 6 2
7 F A E 7 2
# Family 3
2 B <NA> <NA> 2 3
3 C <NA> <NA> 3 3
9 H C B 9 3

编辑:

遗憾的是(好!)在人类遗传学中,我们需要研究类似的变量——家庭、三重奏、妈妈( parent 1、母亲、女性)、父亲(爸爸、 parent 2、男性)、个体/受试者等。这使得一切相似,问题相似。

  Family vs Trio 
1 Nuclear family
A x B
|
C D E

Trio -> 3 trios
A x B A x B A x B
| | |
C D E

发问者的编辑:我同意以下评论作为作业,请暂时不要回答问题(您认为足够好的时间,作业提交时间已经过去)。如果我得到答复,我会稍后发布(3 个月左右)。

编辑

创始人定义 - 那些 parent 双方都不知道他们是否是儿子/女儿的人,所以他们在 MOM 和 DAD 列中都有。这些被认为是家庭 0,因为它们是其他家庭的一部分,但列表不是真正的家庭。

 Person  MOM  DAD Xv     family
1 A <NA> <NA> 1 0
2 B <NA> <NA> 2 0
3 C <NA> <NA> 3 0
10 I <NA> <NA> 10 0
6 E <NA> <NA> 6 0

** 家庭定义* 一个家庭由 parent (妈妈和爸爸)和所有儿子和女儿组成。如果 Person DAD 和 MOM 与 Another Person DAD 和 MOM 匹配,则应将他们视为一个家庭。例如下面列表中的D和E人,MOM=A,DAD=B,这两个人连同D、E组成一个家庭。现在我们需要从创始人列表(家庭 0)中为他们的 parent (A 和 B)回收数据。

 # Family 1
Person MOM DAD Xv family
1 A <NA> <NA> 1 1
2 B <NA> <NA> 2 1
4 D A B 4 1
5 E A B 5 1

同样与人类情况相反,这里的个体可以是 MOM 或 DAD(可以转换性别),因此 A(MOM)和 B(DAD)产生的后代与 B(MOM)和 A 产生的后代相同(DAD),因此我们需要将以下内容添加到 individual to family 1 列表中。

       Person  MOM   DAD     Xv     family
8 G B A 8 1

因此家庭 1 的完整列表变为:

     Person  MOM   DAD Xv     family
1 A <NA> <NA> 1 1
2 B <NA> <NA> 2 1
4 D A B 4 1
5 E A B 5 1
8 G B A 8 1

家庭 1 可以图示为:

            MOM   x   DAD             MOM   x   DAD
A | B or B | A
----------------- ------
| | |
D E G

这是部分解决方案:

myd1 <- data.frame(myd$DAD, myd$MOM) 
myd$family<-as.factor(apply(myd1,1,function(x){paste(x[order(x)],collapse='-')}))
Person MOM DAD Xv family
1 A <NA> <NA> 1 NA-NA
2 B <NA> <NA> 2 NA-NA
3 C <NA> <NA> 3 NA-NA
4 D A B 4 A-B
5 E A B 5 A-B
6 E <NA> <NA> 6 NA-NA
7 F A E 7 A-E
8 G B A 8 A-B
9 H C B 9 B-C
10 I <NA> <NA> 10 NA-NA

它不提供家族编号,而是 A 和 B 的家族。NA-NA 是创始人,它在崩溃前下令,因此 A-B 变成 B-A。

剩下的问题是 A-B 家庭需要回收人员 A 和 B 的数据(尽管他们在家庭 NA-NA 组中)。

  Person  MOM  DAD Xv family
1 A <NA> <NA> 1 NA-NA
2 B <NA> <NA> 2 NA-NA
4 D A B 4 A-B
5 E A B 5 A-B

最佳答案

我不确定您是否已经解决了这个问题,但这是一个解决方案。

首先,您的数据:

# Your data
myd <- data.frame(Person = c("A", "B", "C", "D", "E",
"E", "F", "G", "H", "I"),
MOM = c(NA, NA, NA, "A", "A", NA, "A", "B", "C", NA),
DAD = c(NA, NA, NA, "B", "B", NA, "E", "A", "B", NA),
Xv = 1:10, stringsAsFactors=F)

其次,我们通过将原始数据中的第 2 列和第 3 列合并在一起来识别家族。我们将使用它来拆分您的 data.frame 到一个列表中。

# Identifying the families
fam = apply(myd[2:3], 1, function(x) paste0(sort(x), collapse=" "))

第三,我们将data.frame拆分成一个列表。在这种情况下,我们最终得到一个包含四个 data.frame 的列表:一个用于创始人,一个用于每个家族。

# Splitting the data by founders and families
temp_1 = split(myd, fam)
names(temp_1)[1] = "Founders"

第四,我们进行一些简单的匹配和子集化,以确定哪些创始人属于哪些家族。

# Identify which families the founders belong to
temp_2 = lapply(1:length(temp_1),
function(x) temp_1[[1]][which(temp_1[[1]]$Person %in%
unique(unlist(temp_1[[x]][,c(2,3)], use.names=FALSE))),])

最后,我们将这些数据rbind 在一起。

# "Merging" (with rbind) founders and their families
OUT = lapply(1:length(temp_1), function(x) rbind(temp_2[[x]], temp_1[[x]]))
names(OUT) = names(temp_1)

这是输出:

OUT
# $Founders
# Person MOM DAD Xv
# 1 A <NA> <NA> 1
# 2 B <NA> <NA> 2
# 3 C <NA> <NA> 3
# 6 E <NA> <NA> 6
# 10 I <NA> <NA> 10
#
# $`A B`
# Person MOM DAD Xv
# 1 A <NA> <NA> 1
# 2 B <NA> <NA> 2
# 4 D A B 4
# 5 E A B 5
# 8 G B A 8
#
# $`A E`
# Person MOM DAD Xv
# 1 A <NA> <NA> 1
# 6 E <NA> <NA> 6
# 7 F A E 7
#
# $`B C`
# Person MOM DAD Xv
# 2 B <NA> <NA> 2
# 3 C <NA> <NA> 3
# 9 H C B 9

更新:data.frame 输出

如果您更喜欢 data.frame 而不是 list,您可以完成前面的步骤后执行以下操作:

OUT = do.call("rbind", 
lapply(1:length(OUT),
function(x) cbind(OUT[[x]], fam = names(OUT[x]))))
OUT
# Person MOM DAD Xv fam
# 1 A <NA> <NA> 1 Founders
# 2 B <NA> <NA> 2 Founders
# 3 C <NA> <NA> 3 Founders
# 6 E <NA> <NA> 6 Founders
# 10 I <NA> <NA> 10 Founders
# 11 A <NA> <NA> 1 A B
# 21 B <NA> <NA> 2 A B
# 4 D A B 4 A B
# 5 E A B 5 A B
# 8 G B A 8 A B
# 12 A <NA> <NA> 1 A E
# 61 E <NA> <NA> 6 A E
# 7 F A E 7 A E
# 22 B <NA> <NA> 2 B C
# 31 C <NA> <NA> 3 B C
# 9 H C B 9 B C

关于r - 在 R 中生成组(家庭),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11515970/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com