This would be one of the many ways it can be done. There might be some more efficient ways:
# Create the original dataset
data <- data.frame(V1 = c(1,2,3,9,9,"a"), V2 = c(2,2,5,8,9,2))
# Check if V1 == V2 and write the result to V3 for ALL observations
data$V3 <- data$V1 == data$V2
# Where V1 or V2 are not in the range [1,8], overwrite V3 with NA
data$V3[!(grepl("\\b[12345678]\\b", data$V2) &
grepl("\\b[12345678]\\b", data$V1))] <- NA
Where the "\\b[12345678]{1,1}\\b"
can be decomposed as follows:
1) the [12345678] part check, if the string contains some number from the range 1:8.
2) the \bb ... \bb part gives you the word boundary - thus number 2 will be matched, but number 28 will not.
If you wanted to match a range 0:13, you would adjust the regular expression like this:
data$V3[!(grepl("\\b([0-9]|1[0-3])\\b", data$V2) &
grepl("\\b([0-9]|1[0-3])\\b", data$V1))] <- NA
Where the \\b([0-9]|1[0-3])\\b
can be translated as follows:
1) [0-9] matches numbers 0:9
2) 1[0-3] matches numbers 10:13
3) [0-9]|1[0-3] tells you that numbers 0:9 or 10:13 should be matched
4) \b...\b gives you the word boundaries
5) (...) tells you that the word boundaries should be evaluated after the expression within brackets. Without the brackets, this would be equivalent operation: \\b[0-9]\\b|\\b1[0-3]\\b
For more detailed introduction into matching numeric ranges
with regular expression
see this link: http://www.regular-expressions.info/numericranges.html