[英]Pairing rows in data.table
我有一個類似於使用以下命令獲得的數據表:
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',然后刪除行的后半部分。 但是,我不確定這是否適用於所有情況,我想學習更好的方法來執行此操作。
假設您的數據看起來像您的示例數據:
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
工作方式)。
其他方式:
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)
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.