3
votes
DF <- data.frame("ID" = c(901, 902, 903, 904, 909), "INT" = c(0, 1, 0, 1, 1))

> DF
   ID INT
1 901   0
2 902   1
3 903   0
4 904   1
5 909   1

I want to replace "9" in the ID column when INT = 1, so, it should look like following:

 New_DF
   ID INT
1 901   0
2 802   1
3 903   0
4 804   1
5 809   1

I have tried this

if(DF$INT == "1") {
  gsub("^9", "8", DF$ID) 
}

It gives me the following error:

Warning message: In if (DF$INT == "1") { : the condition has length > 1 and only the first element will be used

5

5 Answers

3
votes

You need to use the ifelse() function.

DF$ID <- ifelse(DF$INT == 1,  gsub("^9", "8", DF$ID), DF$ID)

Using dplyr:

DF %>% 
   mutate(ID=ifelse(INT==1,gsub("^9","8",ID),ID))

This will run the gsub on the rows where DF$INT == 1, and if it's not 1 then it will remain the same.

The if() function that you used:

if(DF$INT == "1") { }

is not intended to work on data.frames. The if() function is used only to check if something (like a statement) is TRUE or FALSE. For example:

if(use_new_function == "on"){ 
    run_new_function() 
}
2
votes

You can use log to find the number of digits and then subtract 10 raised to the number of digits based if INT is 1. This way, ID will still be numeric.

digits = floor(log(DF$ID, 10))
transform(DF, ID = ID - (10^digits) * (floor(ID/(10^digits)) == 9) * (INT))
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1
1
votes

We could first find indices where INT is 1 and then use sub to replace the values at that indices.

inds <- DF$INT == 1
DF$ID[inds] <- as.integer(sub("^9", "8", DF$ID[inds]))

DF
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1

Or we can also use ifelse

as.integer(ifelse(DF$INT == 1, sub("^9", "8", DF$ID), DF$ID))
#[1] 901 802 903 804 809
1
votes

The substring can be used for assignment. Create a logical index based on the 'INT' column and by checking if the first character of 'ID" is 9 ('i1'), then use substring for assigning the first character of 'ID' to '8'

i1 <- as.logical(DF$INT) & substr(DF$ID, 1, 1) =='9'
substring(DF$ID[i1], 1, 1) <- '8'
DF
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1

data

DF <- structure(list(ID = c("901", "902", "903", "904", "909"), 
 INT = c(0, 
  1, 0, 1, 1)), row.names = c(NA, -5L), class = "data.frame")
0
votes

As in your example data DF both columns are numeric you can simply use

DF$ID[DF$INT==1] <- DF$ID[DF$INT==1] - 100

If the column ID is a string you can use gsub like:

DF$ID <- as.character(DF$ID)
DF$ID[DF$INT==1] <- gsub("^9", "8", DF$ID[DF$INT==1])
#   ID INT
#1 901   0
#2 802   1
#3 903   0
#4 804   1
#5 809   1

which places your if(DF$INT == "1") to a data subset [DF$INT==1]