I am trying to replace every row's values in 2 columns with a vector of length 2. It is easier to show you.
First here is a some data.
set.seed(1234) 
x<-data.frame(x=sample(c(0:3), 10, replace=T))
x$ab<-0 #column that will be replaced
x$cd<-0 #column that will be replaced
The data looks like this:
   x ab cd
1  0  0  0
2  2  0  0
3  2  0  0
4  2  0  0
5  3  0  0
6  2  0  0
7  0  0  0
8  0  0  0
9  2  0  0
10 2  0  0
Every time x=2 or x=3, I want to ab=0 and cd=1.
My attempt is this:
x[with(x, which(x==2|x==3)), c(2:3)] <- c(0,1)
Which does not have the intended results:
   x ab cd
1  0  0  0
2  2  0  1
3  2  1  0
4  2  0  1
5  3  1  0
6  2  0  1
7  0  0  0
8  0  0  0
9  2  1  0
10 2  0  1
Can you help me?
The reason it doesn't work as you want is because R stores matrices and arrays in column-major layout. And when you a assign a shorter array to a longer array, R cycles through the shorter array. For example if you have
x<-rep(0,20)
x[1:10]<-c(2,3)
then you end up with
 [1] 2 3 2 3 2 3 2 3 2 3 0 0 0 0 0 0 0 0 0 0
What is happening in your case is that the sub-array where x is equal to 2 or 3 is being filled in column-wise by cycling through the vector c(0,1).  I don't know of any simple way to change this behavior.
Probably the easiest thing to do here is simply fill in the columns one at a time. Or, you could do something like this:
indices<-with(x, which(x==2|x==3))
x[indices,c(2,3)]<-rep(c(0,1),each=length(indices))
                        Another alternative: Using a data.table, this is a one-liner:
require(data.table)
DT <- data.table(x)
DT[x%in%2:3,`:=`(ab=0,cd=1)]
Original answer: You can pass a matrix of row-column pairs:
ijs <- expand.grid(with(x, which(x==2|x==3)),c(2:3))
ijs <- ijs[order(ijs$Var1),]
x[as.matrix(ijs)] <- c(0,1)
which yields
   x ab cd
1  0  0  0
2  2  0  1
3  2  0  1
4  2  0  1
5  3  0  1
6  2  0  1
7  0  0  0
8  0  0  0
9  2  0  1
10 2  0  1
My original answer worked on my computer, but not a commenter's.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With