我目前有一个数据表,其中包含两列-'id'和'prevId'。我想通过从第一行开始,找到第二行,找到其“ id”等于第一行的“ prevId”,然后重复此过程直到“ prevId”为空白,来创建ID链。
然后,我想在链的末尾标识没有“ prevId”的“ id”,并创建一个新列,为每一行列出该发起者“ id”。
下面是我想要的输出的一个示例:
id prevId originatorId createdAt
1: 11a 11a 2018/1/12
2: 11b 11a 11a 2018/1/13
3: 11c 11b 11a 2018/1/14
4: 12a 12a 2018/1/12
5: 12b 12a 12a 2018/1/13
任何指导将不胜感激,谢谢!
编辑:
在测试某些建议的解决方案时,我注意到了一个警告。在某些情况下,某个元素的“ prevId”在任何其他元素中都不会被视为“ id”。如果要用来运行chinsoon的解决方案:
DT[, originatorId:=id[1L], by=cumsum(prevId==“”)]
这将导致此类元素将没有“ prevId”的最接近对等方列出为发起方,即使该对等方不属于id-prevId链。一个例子:
id prevId originatorId createdAt
1: 10a 10a 2018/1/12
2: 11b 11a 10a 2018/1/13
3: 11c 11b 10a 2018/1/14
在这种情况下,“ 11a”应该是第二个和第三个元素的始发者,但是由于它不存在,因此“ 10a”代替了它。有没有可以解决此问题的调整?非常感谢。
答案 0 :(得分:0)
我设法通过定义递归函数并将其应用于所有行来解决此问题。
image.Width - right
答案 1 :(得分:0)
现在可以通过两个递归步骤使用const scriptsWithKeywordCount = $('script:contains("zopim")').length;
if (scriptsWithKeywordCount > 0) {
// webpage contains keyword in javascript code
}
和dplyr
功能进行递归。
data.table
扩展了示例,以包含@Michael的注释。它具有很好的可扩展性,并且可以通过在管道中添加其他联接来调整递归步骤的数量。每次迭代后,它都会保存生成的联接数据表,因此可以轻松地执行匹配步骤。最后,将每个联接的结果组合起来,结果表应该可以很好地概述数据中的ID链。
dt <- structure(list(id = c("11a", "11b", "11c", "12a", "12b"), prevId = c(NA, "11a", "11b", NA, "12a")), row.names = c(NA, -5L), class = c("data.table", "data.frame"))
data.table(left_join(x = dt
, y = dt[,.(prevId)]
, by = c("id" = "prevId")) %>% left_join(
y = dt[,.(id,prevId)]
, by = c("prevId" = "id")
))[, .(id, prevId, originatorId = ifelse(is.na(prevId.y), ifelse(is.na(prevId), id, prevId), prevId.y ))]
> id prevId originatorId
1: 11a <NA> 11a
2: 11b 11a 11a
3: 11c 11b 11a
4: 12a <NA> 12a
5: 12b 12a 12a
生成的data.table看起来像这样:
library(dplyr)
left_join(x = dt
, y = dt[,.(prevId)]
, by = c("id" = "prevId")) %>% data.table(.) %>% { . ->> dt.join.1} %>% left_join(x = .
, y = dt[,.(Second.id = id, Second.prevId = prevId)]
, by = c("prevId" = "Second.id")) %>% data.table(.) %>% { . ->> dt.join.2}
dt.join.final.data <- rbindlist(list( dt.join.1
, dt.join.2)
, fill = TRUE
, idcol = "id"
, use.names = TRUE)