我有一个类似于使用以下命令获得的数据表:
dt <- data.table(
time = 1:8,
part = rep(c(1, 1, 2, 2), 2),
type = rep(c('A', 'B'), 4),
data = rep(c(runif(1), 0), 4))
基本上,这样的表包含两种不同类型的实例(A或B)。时间列包含请求到达或离开某个部分的时间戳。如果实例类型为A,则时间戳表示到达时间(输入),如果类型为B,则时间戳表示离开时间(退出)。
time part type data
1: 1 1 A 0.5842668
2: 2 1 B 0.0000000
3: 3 2 A 0.5842668
4: 4 2 B 0.0000000
5: 5 1 A 0.5842668
6: 6 1 B 0.0000000
7: 7 2 A 0.5842668
8: 8 2 B 0.0000000
我想配对A和B实例,并获取以下数据表:
part data enter.time exit.time
1: 1 0.4658239 1 2
2: 1 0.4658239 5 6
3: 2 0.4658239 3 4
4: 2 0.4658239 7 8
我尝试了以下内容:
pair.types <- function(x) {
a.type <- x[type == 'A']
b.type <- x[type == 'B']
return(data.table(
enter.time = a.type$time,
exit.time = b.type$time,
data = a.type$data))
}
dt[, c('enter.time', 'exit.time', 'data') := pair.types(.SD), by = list(part)]
但是,这给了我以下,这不是我想要的:
time part type data enter.time exit.time
1: 1 1 A 0.3441592 1 2
2: 2 1 B 0.3441592 5 6
3: 3 2 A 0.3441592 3 4
4: 4 2 B 0.3441592 7 8
5: 5 1 A 0.3441592 1 2
6: 6 1 B 0.3441592 5 6
7: 7 2 A 0.3441592 3 4
8: 8 2 B 0.3441592 7 8
它有点接近,但由于保留了列'type',所以有些行是重复的。也许,我可以尝试删除列'time'和'type',然后删除行的后半部分。但是,我不确定这是否适用于所有情况,我想学习更好的方法来进行此操作。
答案 0 :(得分:3)
假设您的数据看起来像您的示例数据:
dt[, list(part = part[1],
data = data[1],
enter.time = time[1],
exit.time = time[2]),
by = as.integer((seq_len(nrow(dt)) + 1)/2)]
# by = rep(seq(1, nrow(dt), 2), each = 2)]
# ^^^ a slightly shorter and a little more readable alternative
这个想法非常简单 - 将行分为2组(即by
部分),即每组将是一个A和一个B,然后为每个组首先采用part
和第一个data
然后输入和退出时间分别只是第一个和第二个time
。如果您遵循副手逻辑,这很可能就是这样做的,这使得它易于阅读(一旦您对data.table
的工作方式有所了解)。
答案 1 :(得分:2)
另一种方式:
setkey(dt, "type")
dt.out <- cbind(dt[J("A"), list(part, data, entry.time = time)][, type := NULL],
exit.time = dt[J("B"), list(time)]$time)
# part data entry.time exit.time
# 1: 1 0.1294204 1 2
# 2: 2 0.1294204 3 4
# 3: 1 0.1294204 5 6
# 4: 2 0.1294204 7 8
如果您愿意,现在可以setkey(dt.out, "part")
获得相同的订单。
这个想法:你的问题对我来说似乎是一个简单的“重塑”问题。我接近它的方法是首先创建一个关键列type
。现在,我们可以通过以下方式为关键列中的特定值分组data.table:dt[J("A")]
。这将返回整个data.table
。由于您希望重命名列time
,因此我明确提到要使用子集的哪些列:
dt[J("A"), list(part, data, entry.time = time)]
当然,这也将返回我们要移除的type
列(= A)。因此,我添加了[, type := NULL]
以通过引用删除列type
。
现在我们是第一部分。我们所需要的只是exit.time
。这可以类似地获得:
dt[J("B"), list(time)] # I don't name the column here
但是当你只需要时间列时,这会给出一个data.table
,可以通过以下方式访问:
dt[J("B"), list(time)]$time
因此,在使用cbind
时,我将此列命名为exit.time
,以获得最终结果:
cbind(dt[J("A"), list(part, data, entry.time = time)][, type := NULL],
exit.time = dt[J("B"), list(time)]$time)
希望这有帮助。