我在 R 中有一個初始表,包括 7 個變數,如下所示:
library(data.table)
Data<-data.frame(
ID=c(1,1,1,2,2,2,3,3,3,4,4,4),
CP1 =c(1,0,0,1,0,0,1,0,0,1,0,0),
CP2 =c(0,1,1,0,0,1,0,1,0,0,0,0),
CP3 =c(0,0,0,0,0,0,0,0,0,0,0,1),
PR1 =c(1,1,0,0,0,0,0,0,0,0,0,0),
PR2=c(0,0,1,0,0,0,0,0,0,0,0,0),
PR3=c(0,0,0,0,1,0,0,0,0,0,0,1)
)
Data
> Data
ID CP1 CP2 CP3 PR1 PR2 PR3
1 1 1 0 0 1 0 0
2 1 0 1 0 1 0 0
3 1 0 1 0 0 1 0
4 2 1 0 0 0 0 0
5 2 0 0 0 0 0 1
6 2 0 1 0 0 0 0
7 3 1 0 0 0 0 0
8 3 0 1 0 0 0 0
9 3 0 0 0 0 0 0
10 4 1 0 0 0 0 0
11 4 0 0 0 0 0 0
12 4 0 0 1 0 0 1
我想用 PR1、PR2 和 PR3 變數創建 CP1、CP2 和 CP3 的所有產品組合,其名稱為 CP1_PR1、CP1_PR2、CP1_PR3、CP2_PR1、CP2_PR2、CP2_PR3、CP3_PR1、CP3_PR2 和 CP3_PR3。
但我想用一個條件來做這個產品。當 CP 和 PR 變數都等于 1 時,我想創建等于 1 的 CP_PR 變數,并將初始 CP 變數設為零。
我用 CP 變數的名稱和 PR 變數的向量制作了一個向量:
ListCP<-colnames(Data)[2:4]
ListPr<-colnames(Data)[5:7]
然后我使用雙回圈來創建所需的產品組合變數,它正確地創建了我想要的組合:
for (i in ListPr) {
for (j in ListCP) {
Data<-Data[,paste0(j,"_",i) := ifelse(get(i)==1 & get(j)==1,1,0)]
}
}
> Data
> Data
ID CP1 CP2 CP3 Pr1 Pr2 Pr3 CP1_Pr1 CP2_Pr1 CP3_Pr1 CP1_Pr2 CP2_Pr2 CP3_Pr2 CP1_Pr3 CP2_Pr3 CP3_Pr3
1: 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0
2: 1 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0
3: 1 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0
4: 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5: 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
6: 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
7: 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8: 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
9: 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10: 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11: 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12: 4 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1
然后,當我嘗試將初始 CP 變數設為零時,以防我上面所說的出現錯誤。
> for (i in ListCP) {
for (j in ListPr) {
Data<-Data[paste0(j,"_",i)==1,.(j) := 0]
}
}
Error in `[.data.table`(Data, paste0(j, "_", i) == 1, `:=`(.(j), 0)) :
LHS of := must be a symbol, or an atomic vector (column names or positions).
我的問題是我是否可以將兩個雙 for 回圈合并為一個而不會出錯。此外,由于我的資料集更大,因此將不勝感激任何其他更快的實作。
謝謝你。
uj5u.com熱心網友回復:
以下解決方案使用變數.SD及其隨附的.SDcols,并且只需要一個for回圈。這似乎是一種更自然的方式。
library(data.table)
Data<-data.frame(
ID=c(1,1,1,2,2,2,3,3,3,4,4,4),
CP1 =c(1,0,0,1,0,0,1,0,0,1,0,0),
CP2 =c(0,1,1,0,0,1,0,1,0,0,0,0),
CP3 =c(0,0,0,0,0,0,0,0,0,0,0,1),
PR1 =c(1,1,0,0,0,0,0,0,0,0,0,0),
PR2=c(0,0,1,0,0,0,0,0,0,0,0,0),
PR3=c(0,0,0,0,1,0,0,0,0,0,0,1)
)
Data2 <- as.data.table(Data)
Data <- as.data.table(Data)
ListCP<-colnames(Data)[2:4]
ListPr<-colnames(Data)[5:7]
for (i in ListPr) {
for (j in ListCP) {
Data<-Data[,paste0(j,"_",i) := ifelse(get(i)==1 & get(j)==1,1,0)]
}
}
for(j in ListPr) {
new_cols <- paste0(ListCP, "_", j)
j_val <- Data2[[j]]
Data2[, (new_cols) := lapply(.SD, \(i) (i & j_val)), .SDcols = ListCP]
}
all.equal(Data, Data2)
#> [1] TRUE
由reprex 包(v2.0.1)創建于 2022-02-19
編輯
對于新問題,請嘗試以下操作。
它必須在一個單獨的回圈中運行,首先使用上述CP變數的原始值,然后只有在新列為 1 時才更改為 0。
for(j in ListPr) {
new_cols <- paste0(ListCP, "_", j)
j_val <- Data2[[j]]
Data2[, (ListCP) := ifelse(.SD == 1, 0L, .SD), .SDcols = ListCP, by = new_cols]
}
uj5u.com熱心網友回復:
更新
- 根據 OP 的說明,何時應更新 CP 值:
df = melt(Data[, id:=.I], id="id",measure =patterns("CP", "PR"), value.name = c("CP", "PR"))
prods = list()
for( i in unique(df$variable)) {
for(j in unique(df$variable)) {
prod = merge(df[variable==i], df[variable==j], by="id")[,`:=`(p=CP.x*PR.y)]
df <- df[prod[, .(id,p)], CP:=fifelse(p==1 & variable==i, 0, CP), on="id"]
prods = c(prods,list(setnames(prod[,.(p)],new=paste0("CP",i,"_PR",j))))
}
}
cbind(
Data[, .(ID)],
dcast(df, id~variable, value.var=c("CP","PR"), sep=""),
do.call(cbind, prods)
)[,id:=NULL][]
輸出:
ID CP1 CP2 CP3 PR1 PR2 PR3 CP1_PR1 CP1_PR2 CP1_PR3 CP2_PR1 CP2_PR2 CP2_PR3 CP3_PR1 CP3_PR2 CP3_PR3
1: 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0
2: 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0
3: 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
4: 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5: 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
6: 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
7: 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8: 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
9: 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10: 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11: 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12: 4 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
以前的
這是另一種方法 - 到目前為止僅獲取組合變數,但是當您澄清(請參閱我的評論)哪個產品將確定 CP 是否從 1 替換為 0 時,我會對其進行更新。
setDT(Data)
df = melt(Data[, id:=.I], id="id",measure =patterns("CP", "PR"), value.name = c("CP", "PR"))
result = do.call(cbind, lapply(unique(df$variable), function(i) {
do.call(cbind, lapply(unique(df$variable), function(j) {
result = merge(df[variable==i], df[variable==j], by="id")[,`:=`(p=CP.x*PR.y)]
setnames(result[, .(p)], new=paste0("CP",i,"_PR",j))
}))
}))
cbind(Data, result)[,id:=NULL][]
輸出:
ID CP1 CP2 CP3 PR1 PR2 PR3 CP1_PR1 CP1_PR2 CP1_PR3 CP2_PR1 CP2_PR2 CP2_PR3 CP3_PR1 CP3_PR2 CP3_PR3
1: 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0
2: 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0
3: 1 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0
4: 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5: 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
6: 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
7: 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
8: 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
9: 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10: 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
11: 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12: 4 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1```
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/429109.html
