R:data.table 比较行集
R: data.table compare sets of rows
我和 data.tables 一起在 R 中工作。我有以下 data.table 编码一组坐标为 A、B、C、D 的点和索引编码该点所属的一组点。
library(data.table)
A B C D set
1: 0 0 0 0 1
2: 1 0 1 0 2
3: 1 1 1 0 2
4: 0 1 0 0 2
5: 1 0 1 1 2
6: 0 1 0 0 3
7: 1 1 0 0 3
8: 0 0 1 0 4
9: 1 0 1 0 4
10: 0 1 0 1 4
11: 0 0 0 0 5
12: 1 0 0 0 5
13: 1 1 1 0 5
14: 1 1 1 1 5
dt = setDT(structure(list(A = c(0L, 1L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L,
0L, 1L, 1L, 1L), B = c(0L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 1L,
0L, 0L, 1L, 1L), C = c(0L, 1L, 1L, 0L, 1L, 0L, 0L, 1L, 1L, 0L,
0L, 0L, 1L, 1L), D = c(0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L,
0L, 0L, 0L, 1L), set = c(1L, 2L, 2L, 2L, 2L, 3L, 3L, 4L, 4L,
4L, 5L, 5L, 5L, 5L)), .Names = c("A", "B", "C", "D", "set"), row.names = c(NA,
-14L), class = "data.frame"))
我有另一个 table 编码,例如每组的概率。
set mass
1: 1 0.27809187
2: 2 0.02614841
3: 3 0.36890459
4: 4 0.28975265
5: 5 0.03710247
wt = setDT(structure(list(set = 1:5, mass = c(0.27809187, 0.02614841, 0.36890459,
0.28975265, 0.03710247)), .Names = c("set", "mass"), row.names = c(NA,
-5L), class = "data.frame"))
我想要一个程序来创建到子空间的投影,例如光盘。 (请注意,原始点 1,4,6,7,11,12 在这种情况下重合,集合 1 和 3 在该子空间以及集合 2 和 5 中相同。
unique(dt[,c("C","D", "set")])
> C D set
1: 0 0 1
2: 1 0 2
3: 0 0 2
4: 1 1 2
5: 0 0 3
6: 1 0 4
7: 0 1 4
8: 0 0 5
9: 1 0 5
10: 1 1 5
为了识别相同的集合,只保留唯一的集合并对相应的质量求和。 IE。在这种情况下:
> C D set
1: 0 0 1
2: 1 0 2
3: 0 0 2
4: 1 1 2
5: 1 0 4
6: 0 1 4
set mass
1: 1 0.6469965 % set 1 + set 3
2: 2 0.06325088 % set 2 + set 5
3: 4 0.36890459
谢谢你的想法。
一个有点笨拙的选项:为每组创建一个唯一的字符串,然后对其进行分组。
coords = c("C", "D")
gDT = setorder(unique(dt[,c(coords, "set"), with=FALSE]))[,
.(s = paste(do.call(paste, c(.SD, .(sep="_"))), collapse="."))
, by=set, .SDcols = coords][,
g := .GRP
, by=s][]
# set s g
# 1: 1 0_0 1
# 2: 2 0_0.1_0.1_1 2
# 3: 3 0_0 1
# 4: 5 0_0.1_0.1_1 2
# 5: 4 0_1.1_0 3
gDT[wt, on=.(set), mass := i.mass ]
gDT[, .(set = first(set), mass = sum(mass)), by=g]
# g set mass
# 1: 1 1 0.64699646
# 2: 2 2 0.06325088
# 3: 3 4 0.28975265
评论
您可以通过链接最后一行的 [, g := NULL][]
来删除 g
。
setorder
只是对数据进行排序,以便唯一字符串在相同的集合中结果相同。
分组的first
和sum
操作被优化了,你可以看到如果你在最后一行添加verbose = TRUE
,比如gDT[, .(set = first(set), mass = sum(mass)), by=g, verbose=TRUE]
。
与 Frank 的概念类似,我们可以使用 x * 2 ^ ((length(x) - 1):0)
将每个集合的二进制值映射到十进制。同样,对于 "C" 和 "D",我们得到:
coords = c("C", "D")
d = data.frame(set = dt$set,
val = Reduce("+", Map("*", list(dt$C, dt$D), 2 ^ ((length(coords) - 1):0))))
d
然后,我们可以按照相同的想法对相同的集合进行分组:
tab = table(d$val, d$set) > 0L ## `table(d) > 0` to ignore the duplicates
gr = colSums(tab * (2 ^ ((nrow(tab) - 1):0)))
gr
# 1 2 3 4 5
# 8 11 8 6 11
## another (pre-edit) alternative with unnecessary overhead
#gr = cutree(hclust(dist(table(d) > 0L)), h = 0)
#gr
#1 2 3 4 5
#1 2 1 3 2
并根据该组进行汇总:
rowsum(wt$mass[match(names(gr), wt$set)], gr, reorder = FALSE)
# [,1]
#8 0.64699646
#11 0.06325088
#6 0.28975265
我和 data.tables 一起在 R 中工作。我有以下 data.table 编码一组坐标为 A、B、C、D 的点和索引编码该点所属的一组点。
library(data.table)
A B C D set
1: 0 0 0 0 1
2: 1 0 1 0 2
3: 1 1 1 0 2
4: 0 1 0 0 2
5: 1 0 1 1 2
6: 0 1 0 0 3
7: 1 1 0 0 3
8: 0 0 1 0 4
9: 1 0 1 0 4
10: 0 1 0 1 4
11: 0 0 0 0 5
12: 1 0 0 0 5
13: 1 1 1 0 5
14: 1 1 1 1 5
dt = setDT(structure(list(A = c(0L, 1L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L,
0L, 1L, 1L, 1L), B = c(0L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 1L,
0L, 0L, 1L, 1L), C = c(0L, 1L, 1L, 0L, 1L, 0L, 0L, 1L, 1L, 0L,
0L, 0L, 1L, 1L), D = c(0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L,
0L, 0L, 0L, 1L), set = c(1L, 2L, 2L, 2L, 2L, 3L, 3L, 4L, 4L,
4L, 5L, 5L, 5L, 5L)), .Names = c("A", "B", "C", "D", "set"), row.names = c(NA,
-14L), class = "data.frame"))
我有另一个 table 编码,例如每组的概率。
set mass
1: 1 0.27809187
2: 2 0.02614841
3: 3 0.36890459
4: 4 0.28975265
5: 5 0.03710247
wt = setDT(structure(list(set = 1:5, mass = c(0.27809187, 0.02614841, 0.36890459,
0.28975265, 0.03710247)), .Names = c("set", "mass"), row.names = c(NA,
-5L), class = "data.frame"))
我想要一个程序来创建到子空间的投影,例如光盘。 (请注意,原始点 1,4,6,7,11,12 在这种情况下重合,集合 1 和 3 在该子空间以及集合 2 和 5 中相同。
unique(dt[,c("C","D", "set")])
> C D set
1: 0 0 1
2: 1 0 2
3: 0 0 2
4: 1 1 2
5: 0 0 3
6: 1 0 4
7: 0 1 4
8: 0 0 5
9: 1 0 5
10: 1 1 5
为了识别相同的集合,只保留唯一的集合并对相应的质量求和。 IE。在这种情况下:
> C D set
1: 0 0 1
2: 1 0 2
3: 0 0 2
4: 1 1 2
5: 1 0 4
6: 0 1 4
set mass
1: 1 0.6469965 % set 1 + set 3
2: 2 0.06325088 % set 2 + set 5
3: 4 0.36890459
谢谢你的想法。
一个有点笨拙的选项:为每组创建一个唯一的字符串,然后对其进行分组。
coords = c("C", "D")
gDT = setorder(unique(dt[,c(coords, "set"), with=FALSE]))[,
.(s = paste(do.call(paste, c(.SD, .(sep="_"))), collapse="."))
, by=set, .SDcols = coords][,
g := .GRP
, by=s][]
# set s g
# 1: 1 0_0 1
# 2: 2 0_0.1_0.1_1 2
# 3: 3 0_0 1
# 4: 5 0_0.1_0.1_1 2
# 5: 4 0_1.1_0 3
gDT[wt, on=.(set), mass := i.mass ]
gDT[, .(set = first(set), mass = sum(mass)), by=g]
# g set mass
# 1: 1 1 0.64699646
# 2: 2 2 0.06325088
# 3: 3 4 0.28975265
评论
您可以通过链接最后一行的
[, g := NULL][]
来删除g
。setorder
只是对数据进行排序,以便唯一字符串在相同的集合中结果相同。分组的
first
和sum
操作被优化了,你可以看到如果你在最后一行添加verbose = TRUE
,比如gDT[, .(set = first(set), mass = sum(mass)), by=g, verbose=TRUE]
。
与 Frank 的概念类似,我们可以使用 x * 2 ^ ((length(x) - 1):0)
将每个集合的二进制值映射到十进制。同样,对于 "C" 和 "D",我们得到:
coords = c("C", "D")
d = data.frame(set = dt$set,
val = Reduce("+", Map("*", list(dt$C, dt$D), 2 ^ ((length(coords) - 1):0))))
d
然后,我们可以按照相同的想法对相同的集合进行分组:
tab = table(d$val, d$set) > 0L ## `table(d) > 0` to ignore the duplicates
gr = colSums(tab * (2 ^ ((nrow(tab) - 1):0)))
gr
# 1 2 3 4 5
# 8 11 8 6 11
## another (pre-edit) alternative with unnecessary overhead
#gr = cutree(hclust(dist(table(d) > 0L)), h = 0)
#gr
#1 2 3 4 5
#1 2 1 3 2
并根据该组进行汇总:
rowsum(wt$mass[match(names(gr), wt$set)], gr, reorder = FALSE)
# [,1]
#8 0.64699646
#11 0.06325088
#6 0.28975265