【发布时间】:2021-12-13 23:51:35
【问题描述】:
我有以下问题。我有一个在data.table sets 中编码的集合列表,其中id.s 编码集合的ID,id.e 编码它的元素。
对于每个集合 s,都有其值 m(s)。函数 m() 的值在另一个 data.table m 中,其中每一行包含集合 id.s 及其 value 的 id。
sets <- data.table(
id.s = c(1,2,2,3,3,3,4,4,4,4),
id.e = c(3,3,4,2,3,4,1,2,3,4))
v <- data.table(id.s = 1:4, value = c(1/10,2/10,3/10,4/10))
我需要计算新函数 v'() 这样
其中|s|表示集合s的基数(元素个数),b\a表示集合减法(a修改集合 b 的方法是移除带有集合 a 的关节元素)
现在,我使用 for 循环逐行更新。然而,对于包含数千个集合和数千个元素的大型 data.tables,它需要太多时间。
你知道如何让它更容易吗?
我当前的代码:
# convert data.table to wide format
dc <- dcast(sets, id.s ~ id.e, drop = FALSE, value.var = "id.e" , fill = 0)
# take columns corresponding to elements id.e
cols <- names(dc)[-1]
# convert columns cols to 0-1 coding
dc[, (cols) := lapply(.SD, function(x) ifelse(x > 0,1,0)), .SDcols = cols]
# join dc with v
dc <- dc[v, on = "id.s"]
# calculate the cardinality of each set
dc[, cardinality := sum(.SD > 0), .SDcols = cols, by = id.s]
# prepare column for new value
dc[, value2 := 0]
# id.s 1 2 3 4 value cardinality value2
#1: 1 0 0 1 0 0.1 1 0
#2: 2 0 0 1 1 0.2 2 0
#3: 3 0 1 1 1 0.3 3 0
#4: 4 1 1 1 1 0.4 4 0
# for each set (row of dc)
for(i in 1:nrow(dc)) {
row <- dc[i,]
set <- as.numeric(row[,cols, with = F])
row.cardinality <- as.numeric(row$cardinality)
# find its supersets
dc[,is.superset := ifelse(rowSums(mapply("*",dc[,cols,with=FALSE],set))==row.cardinality,1,0)][]
# use the formula to update the value
res <- dc[is.superset==1,][, sum := sum((-1)^(cardinality - row.cardinality)*value)]$sum[1]
dc[i,value2 := res]
}
dc[,.(id.s, value2), with = TRUE]
# id.s value2
#1: 1 -0.2
#2: 2 0.3
#3: 3 -0.1
#4: 4 0.4
【问题讨论】:
标签: r data.table conditional-statements updating