Reputation: 1106
I have to perform row wise logical operation in data table, let me explain this with example. Suppose I have data table (DT) as given below
V1 V2 V3 V4 V5
AAE CDG 2 0 0
AAE CDG 2 5 5
AAE ORY 2 4 4
AAE ORY 2 0 0
AAE ORY 2 5 5
AAE ORY 2 3 3
Now, depending upon the value of V5, I want to add additional column V6 to data table, this is logical operation. I did something like this to do it-
DT[, V6 := if(V5 == 0){1
}else if(V5 == 1){2
}else if(V5 == 2){3
}else if(V5 == 3){4
}else if(V5 == 4){5
}else if(V5 == 5){6}
]
But this does not give the desired result, which should be
V1 V2 V3 V4 V5 V6
AAE CDG 2 0 0 1
AAE CDG 2 5 5 6
AAE ORY 2 4 4 5
AAE ORY 2 0 0 1
AAE ORY 2 5 5 6
AAE ORY 2 3 3 4
Whereas gives the following result-
V1 V2 V3 V4 V5 V6
AAE CDG 2 0 0 1
AAE CDG 2 5 5 1
AAE ORY 2 4 4 1
AAE ORY 2 0 0 1
AAE ORY 2 5 5 1
AAE ORY 2 3 3 1
This happens because first value of V5 (which is 0) is used in logical operation, instead of dynamically using one value or row value at a time. How can I change [,J] argument to get the desired results. I can use the for loop to do this, but it would be very in-efficient way of doing it.
Upvotes: 2
Views: 2177
Reputation: 49448
The other answers so far are in data.frame
language. In data.table
language you should use DT[, V6 := ifelse...]
as opposed to DT$V6 <- ifelse...
and you'd use the [
instead of calling merge
:
setkey(DT, V5)
DT[J(V5 = 0:5, V6 = 1:6), nomatch = 0]
But at least in the example in the OP it looks like the solution is simply:
DT[, V6 := V5 + 1]
Oh, and the reason your if/else
doesn't work is because if/else
doesn't operate on vectors and it simply takes the first value of your vector V5
, which is indeed 0
, and returns 1
, which is effectively the same as writing DT[, V6 := 1]
.
Upvotes: 2
Reputation: 56004
Try this:
dat <- read.table(
text= "V1 V2 V3 V4 V5
AAE CDG 2 0 0
AAE CDG 2 5 5
AAE ORY 2 4 4
AAE ORY 2 0 0
AAE ORY 2 5 5
AAE ORY 2 3 3",header=TRUE)
dat$V6 <- ifelse(dat$V5 == 0,1,
ifelse(dat$V5 == 1,2,
ifelse(dat$V5 == 2,3,
ifelse(dat$V5 == 3,4,
ifelse(dat$V5 == 4,5,
ifelse(dat$V5 == 5,6,NA))))))
Upvotes: 1
Reputation: 1895
Why don't you just do
dat <- read.table(text= "V1 V2 V3 V4 V5
+ AAE CDG 2 0 0
+ AAE CDG 2 5 5
+ AAE ORY 2 4 4
+ AAE ORY 2 0 0
+ AAE ORY 2 5 5
+ AAE ORY 2 3 3 ",header=TRUE)
dat$V6 <- dat$V5 + 1
As @Steph said you can create a mapping table as follows and then merge the columns.
mapping <- data.frame(V5=c(0,1,2,3,4,5),V6=c(1,2,3,4,5,6))
merge(dat,mapping,by="V5")
Upvotes: 2