我無法在任何地方找到答案,我可能沒有找到正確的搜索條件或無法將問題轉移到我的。如何在不使用兩個for-loops的情況下填充我的data.table?
所以我希望這裏有人能夠幫助我。
我有以下形式(我試圖保持它短,但包括所有可能需要)一個data.table DT1:
ID session
101 1
101 1
101 2
101 4
102 2
102 4
102 5
103 1
103 4
201 1
201 4
201 5
202 1
202 2
203 1
204 5
代碼重現此:
dt1 <- data.table(ID=c(101, 101, 101, 101, 102, 102, 102, 103, 103, 201, 201, 201, 202, 202, 203, 204), session=c(1, 1, 2, 4, 2, 4, 5, 1, 4, 1, 4, 5, 1, 2, 1, 5))
我想要的第一步是在表單中創建一個data.table,其中當輸入data.frame中有一個條目時,每個會話都有一個1,如果沒有,則爲0。
ID 1 2 3 4 5
101 1 1 0 1 0
102 0 1 0 1 1
103 1 0 0 1 0
201 1 0 0 1 1
202 1 1 0 0 0
203 1 0 0 0 0
204 0 0 0 0 1
現在,我生成兩個列表,
IDs <- sort(unique(dt1$ID))
sessions <- unique(dt1$session)
空data.table dt2
與ncol=length(sessions)
和nrow=length(IDs)
,與會話作爲列名
dt2 <- data.table(matrix(ncol=length(sessions), nrow=length(IDs)))
colnames(dt2) <- as.character(unique(dt1$session))
和列表每個ID都有會話。
sesID <- split(dt1$session, dt1$ID)
然後,我用兩個for循環遍歷列表。
for (i in 1:nrow(dt2)) {
for (j in 1:length(dt2)) {
if (sessions[j] %in% sesID[i]) {
set(dt2, i, j, 1)s
}
else {
set(dt2, i, j, 0)
} } }
作爲第二步,我想要將所有的0更改爲1,如果會話位於具有1s的會話之間。
ID 1 2 3 4 5
101 1 1 1 1 0
102 0 1 1 1 1
103 1 1 1 1 0
201 1 0 0 1 1
202 1 1 0 0 0
203 1 0 0 0 0
204 0 0 0 0 1
我這樣做與另外兩個for循環。
for (i in 1:nrow(dt2)) {
trues <- which(dt2[i,]==1)
headTrues <- head(trues, 1)
tailTrues <- tail(trues, 1)
for (j in 1:length(dt2)){
if (j > headTrues & j < tailTrues & headTrues <= tailTrues){
set(dt2, i, j, 1)
} } }
由於這會生成一個data.table dt3,其中包含TRUE和FALSE,因此我將其替換。
(to.replace <- names(which(sapply(dt3, is.logical))))
for (var in to.replace) dt3[, var:= as.numeric(get(var)), with=FALSE]
爲了將ID保留爲列,我在後面添加它們。
dt3$ID <- IDs
如果我沒有大約12000個唯一ID並需要做幾千次運行,這樣可以。我非常肯定,在R中有更好的方法來做到這一點。我現在還沒有。
非常感謝您提前。
請參見'幫助( 「dcast.data.table」)'爲先步。 – Roland