我有以下类型的数据:
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 and Dad列。我想为这些数据创建族群。 NA缺少信息。定义一个具有共同MOM和DAD的族。创始人是NA,家庭= 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
上述功能在某种意义上是不完美的: 家庭数据不包括其父母的数据,例如家庭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族是同一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
编辑:
遗憾(好!)在人类遗传学中我们需要处理类似的变量 - 家庭,三重奏,妈妈(父母1,母亲,女性),父亲(父亲,父母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个月左右)。
编辑
创始人的定义 - 那些父母双方都不知道他们是否是儿子/女儿的人,所以他们都有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
**家庭定义 * 一个家庭由父母(妈妈和DAD)以及所有儿子和女儿组成。如果Person DAD和MOM与另一个人DAD和MOM匹配,则应将他们视为一个家庭。例如,以下列表中的D和E人具有MOM = A和DAD = B,这两个人与D和E一起由一个家庭组成。现在我们需要从创始人列表(家庭0)回收父母(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),因此我们需要将以下内容添加到个人家庭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
答案 0 :(得分:3)
我不确定你是否已经解决了这个问题,但这是一个解决方案。
首先,您的数据:
# 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列合并在一起来识别族。我们将split
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
如果您更喜欢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
,则可以在完成上述步骤后执行以下:
{{1}}
答案 1 :(得分:2)
如果你想要一个对每个“家庭”来说相同的字符向量,那么使用interaction
函数会更紧凑。这些方面的东西:
myd$fam <- with( myd, as.character( interaction(MOM,DAD)))
myd$fam[ is.na(myd$fam) ] <- 0
如果您想要数字(这看似不明智,但这就是您提出请求的方式),请使用as.character
as.numeric
。
myd$fam <- with( myd, as.numeric( interaction(MOM,DAD)))
myd$fam[ is.na(myd$fam) ] <- 0
我从未弄清楚你怎么能有“A”代表MOM和DAD。您可能需要努力解释您如何理解人类遗传学的这一方面。对于按家庭分组split
> split(myd, myd$fam)
$`0`
Person MOM DAD Xv fam
1 A <NA> <NA> 1 0
2 B <NA> <NA> 2 0
3 C <NA> <NA> 3 0
6 E <NA> <NA> 6 0
10 I <NA> <NA> 10 0
$`2`
Person MOM DAD Xv fam
8 G B A 8 2
$`4`
Person MOM DAD Xv fam
4 D A B 4 4
5 E A B 5 4
$`6`
Person MOM DAD Xv fam
9 H C B 9 6
$`7`
Person MOM DAD Xv fam
7 F A E 7 7