我有两个data.table
s
DT <- data.table(name = c("a","b","c","d"),
"850Hz" = c(0,1,1,0),
"1800Hz" = c(2,0,2,0),
"2100Hz" = c(0,3,0,3),
"2600Hz" = c(4,0,0,4))
Info <- data.table(Freq = c("850Hz", "1800Hz", "2100Hz", "2600Hz"), Rng = c(3000, 2000, 1800, 1000))
我想在DT中创建一个名为“Range”的新列,对每一行进行如下操作:
如果行在“850Hz”列中包含不同于0的数字,则应考虑值3000(根据data.table
信息中“850Hz”和3000之间建立的关联)。然后,如果“1800Hz”列中存在非零数字,则应考虑值2000,以此类推其他2列。最后,它应该计算该行的所有考虑值的最大值,并将其写入新列“Range”中。
等等其他行。
有人建议我使用这段代码:
Info[, {
DT[, Range := pmax(Range, (get(Freq) != 0) * Rng, na.rm = TRUE)]
NULL
}, by = Freq]
我不明白它是如何工作的,但它确实起了作用。我的问题是,为什么我想要为每行而不是最大值的MINIMUM考虑值?如果我使用pmin
,对于此特定示例,“范围”列中的所有值都将为0,因为 会考虑列中值为0的情况(“850Hz”等等,我想它将零乘以相应的值。我需要告诉它忽略这4列中的零。怎么样?
一个可能的答案是将这些列中的所有零转换为N/A
,然后使用na.rm = TRUE。但我无法弄清楚如何进行选择性替换。要考虑的列数(850Hz,1800Hz,2100Hz,本例中为2600Hz)可能小于4 。这是因为根据数据,这4列中的一个或多个可能会丢失。我需要考虑DT中名称存在于向量Info [,Freq]中的所有列。然后,仅更改N/A
的那些列中的所有0。我每次都在尝试和失败。
答案 0 :(得分:1)
我会以长格式保存主要数据:
DT_long = melt(DT, id="name", variable.name="Freq")[value != 0]
并且可能会添加Rng
Info
列
DT_long[Info, Rng := i.Rng, on="Freq"]
# or
Info_cols = setdiff(names(Info), "Freq")
DT_long[Info, (Info_cols) := mget(Info_cols), on="Freq"]
要以宽屏格式显示摘要,您可以使用dcast
:
res = cbind(
dcast(DT_long, name ~ Freq),
dcast(DT_long, name ~ ., value.var = "Rng", fun = list(min, max))[, name := NULL]
)
name 850Hz 1800Hz 2100Hz 2600Hz Rng_min_. Rng_max_.
1: 1 NA 2 NA 4 1000 2000
2: 2 1 NA 3 NA 1800 3000
3: 3 1 2 NA NA 2000 3000
4: 4 NA NA 3 4 1000 1800
不幸的是,我不知道在最后两列中摆脱尾随_.
的快速方法;也许这个功能将在以后添加。有各种解决方法,如
res = cbind(
dcast(DT_long, name ~ Freq),
DT_long[, c(Rng = list(min = min(Rng), max = max(Rng))), keyby=name][, name := NULL]
)