簡體   English   中英

在data.table中配對行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM