Speed up a while loop that conditionally creates a new variable in R
Do not use explicit loops unless you absolutely have to

Many functions in R are vectorized and your code will be much faster if you leverage this instead of writing your own loops.

For example, you can compute the first part of your newID with a single paste() call:

dat$newID &lt;- paste("Ind", dat$ID)


    x ID change newID
1   1  0      0 Ind 0
2   2  0      0 Ind 0
3   3  0      0 Ind 0
4   4  0      0 Ind 0
5   5  0      1 Ind 0
6   6  0      0 Ind 0
7   7  0      1 Ind 0
8   8  0      0 Ind 0
9   9  0      0 Ind 0
10 10  0      0 Ind 0
11  1  1      1 Ind 1
12  2  1      0 Ind 1
13  3  1      0 Ind 1
14  4  1      0 Ind 1
15  5  1      1 Ind 1
16  6  1      0 Ind 1
17  7  1      1 Ind 1
18  8  1      0 Ind 1
19  9  1      0 Ind 1
...


The second part of your newID is simply the cumulative sum of change

The most tricky part here is to reset the counter each time the ID changes. A way to do this is to use the function by, which will execute a given function on a group of rows depending on the values of a grouping variable (here ID):

by(dat, dat$ID, function(x) {
  cumsum(x$change)
})


dat$ID: 0
 [1] 0 0 0 0 1 1 2 2 2 2
--------------------------------------------------------------------------------------------- 
dat$ID: 1
 [1] 1 1 1 1 2 2 3 3 3 3
--------------------------------------------------------------------------------------------- 
dat$ID: 2
 [1] 1 1 1 1 2 2 3 3 3 3


The two issues here are:


by returns a list so we have to use unlist() before trying to put the result in a data.frame column


dat$newID &lt;- unlist(by(dat, dat$ID, function(x) {
  cumsum(x$change)
}))



because change doesn't start with 1, the values for the first ID are shifted by one. We can fix this by changing the first value manually.


Put everything together

dat$change[1] &lt;- 1

dat$newID &lt;- unlist(by(dat, dat$ID, function(x) {
  cumsum(x$change)
}))

dat$newID &lt;- paste0("Ind ", dat$ID, "|", dat$newID)


And you get exactly the output you were asking for, without any explicit for loops!