【发布时间】:2021-11-16 09:22:47
【问题描述】:
我对 R 的大部分经验都与数据有关。框架的世界。然而,由于我经常不得不与大型 data.frames 作斗争,我决定探索高效的 data.table 世界,因此,我要为学习曲线的后果付出代价。这是我的假设情况:
> sessionInfo()
R version 4.1.1 (2021-08-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19043)
> sessioninfo::package_info()
package * version date lib source
data.table * 1.14.0 2021-02-21 [1] CRAN (R 4.1.1)
我有一张长桌,例如它的名字是创始人
> library(data.table)
nfounder <- 1000
founders <- data.table(ID= seq(1:nfounder),
mum= rep(0, nfounder),
dad= rep(0, nfounder))
另一方面,我有一个短表 (ped.g),其中变量 mum 和 dad 来自于创始人表中的变量 ID,即
ped.g <- data.table(ID= seq(1001, 1003),
mum= c(19,23,23),
dad= c(13,13,19))
因此,谱系表是根据创始人和 ped.g 表构建的
pedigree <- rbind(founders, ped.g)
> pedigree
ID mum dad
1: 1 0 0
2: 2 0 0
3: 3 0 0
4: 4 0 0
5: 5 0 0
---
999: 999 0 0
1000: 1000 0 0
1001: 1001 19 13
1002: 1002 23 13
1003: 1003 23 19
因此,
ID <- pedigree[, ID]
mum <- match(pedigree[, mum], pedigree[, ID], nomatch=NA)
dad <- match(pedigree[, dad], pedigree[, ID], nomatch=NA)
这样
> mum
[1] NA NA NA ... NA NA 19 23 23
> dad
[1] NA NA NA ... NA NA 13 13 19
接下来的步骤包括函数生成(“Generation”,用图解继承的家谱的遗传表示),不管这个函数,关键是谱系表
generation <- function(pedigree) {
ID <- pedigree[, ID]
mum <- match(pedigree[, mum], pedigree[, ID], nomatch=NA)
dad <- match(pedigree[, dad], pedigree[, ID], nomatch=NA)
n <- dim(pedigree)[1]
generOld <- gen <- rep(n + 100, n)
gen[is.na(mum) & is.na(dad)] <- 0
i <- 0
while(!all(generOld == gen)) {
generOld <- gen
gen[mum %in% ID[gen==i]] <- i + 1
gen[dad %in% ID[gen==i]] <- i + 1
i <- i + 1
if(i > n + 10) break
}
pedigree[, gen := gen]
return(pedigree)
}
因此,变量 gen 被添加到谱系表中,因此创始人个人的 gen=0 和第一代的 gen=1
pedigree[, gen := gen]
> pedigree
ID mum dad gen
1: 1 0 0 0
2: 2 0 0 0
3: 3 0 0 0
4: 4 0 0 0
5: 5 0 0 0
---
999: 999 0 0 0
1000: 1000 0 0 0
1001: 1001 19 13 1
1002: 1002 23 13 1
1003: 1003 23 19 1
显然,一切似乎都很好......!然而,这个谱系包括许多未被选为“第一代”作为父母(妈妈、爸爸)的个体(ID)。也就是说,它必须只包括父母 13、19 和 23(属于“第 1 代”)。
因此,为了尝试解决之前的问题(仅保留从创始人 data.table 中选择的父母),我使用了以下方法(代码)
回想一下 ped.g 表是
> ped.g
ID mum dad
1: 1001 19 13
2: 1002 23 13
3: 1003 23 19
ped.tmp <- rbind(founders, ped.g)
parents.G0 <- unique(unlist(ped.g[, c(2, 3)]))
parents.G0 <- as.data.table(parents.G0)
setnames(parents.G0, 'parents.G0', 'parents')
setkey(parents.G0, parents)
setkey(ped.tmp, ID)
founders.new <- ped.tmp[parents.G0]
> founders.new
TreeID mum dad
1: 13 0 0
2: 19 0 0
3: 23 0 0
pedigree.new <- as.data.table(rbind(founders.new, ped.g))
> pedigree.new
ID mum dad
1: 13 0 0
2: 19 0 0
3: 23 0 0
4: 1 19 13
5: 2 23 13
6: 3 23 19
到这里,一切顺利……现在,我将尝试利用前面概述的代码构建“Generation”字段
ID <- pedigree.new[, ID]
mum <- match(pedigree.new[, mum], pedigree.new[, ID], nomatch=NA)
dad <- match(pedigree.new[, dad], pedigree.new[, ID], nomatch=NA)
第一个惊喜(或与早期输出的差异)。现在变量 mum 和 dad 由它们在表 pedigree.new 中的变量 ID 对应的索引位置来表示,而不是像前面的情况那样,用它自己的值(13、19 和 23)来表示,即
> mum
[1] NA NA NA 2 3 3
> dad
[1] NA NA NA 1 1 2
因此,在应用代码创建变量“Generation”时,我得到了错误的结果。也就是说,对于第一代,变量 gen=106 而不是 gen=1。
pedigree.new[, gen := gen]
> pedigree.new
ID mum dad gen
1: 13 0 0 0
2: 19 0 0 0
3: 23 0 0 0
4: 1 19 13 106
5: 2 23 13 106
6: 3 23 19 106
当然,我也尝试过不同的方法来创建表谱系(过滤版)。例如,请参阅下一次尝试。
parents.G0 <- unique(unlist(ped.g[, c(2, 3)]))
parents.G0 <- as.data.table(parents.G0)
setnames(parents.G0, 'parents.G0', 'parents')
founders.new2 <- founders[parents.G0, on=.(ID=parents)]
pedigree.new2 <- rbind(founders.new2, ped.g)
但是,我得到了相同的结果..
> gen
[1] 0 0 0 106 106 106
此外,我比较了两个表的属性和结构(谱系与 pedigre.new),但是,它们看起来相同。过滤时似乎在原始谱系表中丢失了一些东西,我真的想更好地理解为什么 data.table 对象会以这种方式表现。所以任何帮助将不胜感激。
问题的重新表述
-
输入:表谱系
pedigree <- rbind(founders, ped.g) > pedigree ID mum dad 1: 1 0 0 2: 2 0 0 3: 3 0 0 --- 13: 13 0 0 --- 19: 19 0 0 --- 23: 23 0 0 --- 999: 999 0 0 1000: 1000 0 0 1001: 1001 19 13 1002: 1002 23 13 1003: 1003 23 19
2) 处理,此步骤由过滤谱系表组成,以便“保留”:
a) 在谱系表(ID=13,19,23)上等于mum 或dad 字段不同的0 的ID 记录,即
ID mum dad
1: 13 0 0
2: 19 0 0
3: 23 0 0
和 b) 与那些不为零的妈妈和爸爸有关的 ID 记录(ID=1001、1002、1003),即
ID mum dad
1001: 1001 19 13
1002: 1002 23 13
1003: 1003 23 19
3 ) 预期输出:从上一步来看,过滤器谱系表如下所示
> pedigree.new
ID mum dad
1: 13 0 0
2: 19 0 0
3: 23 0 0
4: 1 19 13
5: 2 23 13
6: 3 23 19
这样
ID <- pedigree.new[, ID]
mum <- match(pedigree.new[, mum], pedigree.new[, ID], nomatch=NA)
dad <- match(pedigree.new[, dad], pedigree.new[, ID], nomatch=NA)
> mum
[1] NA NA NA ... NA NA 19 23 23
> dad
[1] NA NA NA ... NA NA 13 13 19
因此,在应用函数生成时,新字段 gen“必须看起来像”
pedigree.new <- generation(pedigree.new)
> pedigree.new
ID mum dad gen
1: 13 0 0 0
2: 19 0 0 0
3: 23 0 0 0
4: 1 19 13 1
5: 2 23 13 1
6: 3 23 19 1
-
一些尝试的示例(审查表创始人和 ped.g 早期概述)
ped.tmp <- rbind(founders, ped.g) parents.G0 <- unique(unlist(ped.g[, c(2, 3)])) parents.G0 <- as.data.table(parents.G0) setnames(parents.G0, 'parents.G0', 'parents') setkey(parents.G0, parents) setkey(ped.tmp, ID) founders.new <- ped.tmp[parents.G0] > founders.new ID mum dad 1: 13 0 0 2: 19 0 0 3: 23 0 0 pedigree.new2 <- as.data.table(rbind(founders.new, ped.g)) > pedigree.new2 ID mum dad 1: 13 0 0 2: 19 0 0 3: 23 0 0 4: 1 19 13 5: 2 23 13 6: 3 23 19 ID <- pedigree.new2[, ID] mum <- match(pedigree.new2[, mum], pedigree.new2[, ID], nomatch=NA) dad <- match(pedigree.new2[, dad], pedigree.new2[, ID], nomatch=NA) > mum [1] NA NA NA 2 3 3 > dad [1] NA NA NA 1 1 2 pedigree.new2 <- generation(pedigree.new2) > pedigree.new2 ID mum dad gen 1: 13 0 0 0 2: 19 0 0 0 3: 23 0 0 0 4: 1001 19 13 106 5: 1002 23 13 106 6: 1003 23 19 106
因此,函数 generation() 无法定义字段 gen(ej。ID=1001、1002 和 1003 的 gen 字段等于 106 而不是 gen=1)。
【问题讨论】:
-
你能用 1. 你的输入来安排你的问题吗? 2.你想要的输出; 3.(不太重要,但因为你已经拥有它)你尝试了什么。很难遵循您想要发生的事情,因此更难提供帮助。
-
Dean,非常感谢您的回答,我重新定义了我的问题,定义了一个名为“生成”的函数,以便维持秩序。然而,关键是过滤后产生的谱系表。也就是说,如果谱系表没问题,则“生成”功能起作用,否则,它不起作用......!
标签: r data.table