How to compare values in two columns and if values are equal keep as is, but if values are different, sum by row

93 Views Asked by At

Using R, I would like to compare values in two columns, if the values are equal I would like to keep them as is, if the values are different, I would like to sum the values in the two columns. This seems like a simple operation but I can't figure out how to do it, have found similar posts on SO but not quite this. Something using ifelse maybe?

example df:

structure(list(colA = c(0, 0, 0, 412.99, 34.43, 117.36, 193.05, 
305.22), colB = c(0, 0, 0, 412.99, 6.89, 0, 193.05, 305.22)), class = "data.frame", row.names = c(1323L, 
5426L, 2772L, 7241L, 2547L, 874L, 5908L, 6830L))

Would like to create new column ("colC") with the row sum of A & B if values are different (in this example, sum 34.43 and 6.89 (for row 2547) and keep 412.99 (row 7241; since value is the same for colA and colB). Additionally, it would be helpful to have another column (say "colD") that somehow states whether rows where same or not (to know which obs where different).

My actual df has 10,000+ observations and 30+ variables (columns). I only want to compare two columns within the 30+ cols I have. Thank you.

2

There are 2 best solutions below

1
Grzegorz Sapijaszko On BEST ANSWER

ifelse() might help.

df <- structure(list(colA = c(0, 0, 0, 412.99, 34.43, 117.36, 193.05, 
                        305.22), colB = c(0, 0, 0, 412.99, 6.89, 0, 193.05, 305.22)), class = "data.frame", row.names = c(1323L, 
                                                                                                                          5426L, 2772L, 7241L, 2547L, 874L, 5908L, 6830L))
df |>
  dplyr::mutate(colC = ifelse(colA == colB, colA, colA+colB))
#>        colA   colB   colC
#> 1323   0.00   0.00   0.00
#> 5426   0.00   0.00   0.00
#> 2772   0.00   0.00   0.00
#> 7241 412.99 412.99 412.99
#> 2547  34.43   6.89  41.32
#> 874  117.36   0.00 117.36
#> 5908 193.05 193.05 193.05
#> 6830 305.22 305.22 305.22

Created on 2023-06-19 with reprex v2.0.2

1
Abraham JA On

Using data.table:

Option 1: Use setDT(df, keep.rownames = TRUE) if row names are important

library(data.table)

df <- structure(list(colA = c(0, 0, 0, 412.99, 34.43, 117.36, 193.05, 305.22), 
                     colB = c(0, 0, 0, 412.99, 6.89, 0, 193.05, 305.22)), 
                class = "data.frame", 
                row.names = c(1323L, 5426L, 2772L, 7241L, 2547L, 874L, 5908L, 6830L))

setDT(df)

df[, `:=`(colC = colA, colD = 1L)]
df[colA != colB, `:=`(colC = colA + colB, colD = 0)][]

     colA   colB   colC colD
1:   0.00   0.00   0.00    1
2:   0.00   0.00   0.00    1
3:   0.00   0.00   0.00    1
4: 412.99 412.99 412.99    1
5:  34.43   6.89  41.32    0
6: 117.36   0.00 117.36    0
7: 193.05 193.05 193.05    1
8: 305.22 305.22 305.22    1

Option 2: Similar to @Grzegorz Sapijaszko answer

library(data.table)

df <- structure(list(colA = c(0, 0, 0, 412.99, 34.43, 117.36, 193.05, 305.22), 
                     colB = c(0, 0, 0, 412.99, 6.89, 0, 193.05, 305.22)), 
                class = "data.frame", 
                row.names = c(1323L, 5426L, 2772L, 7241L, 2547L, 874L, 5908L, 6830L))

setDT(df)

df[, colC := fifelse(colA == colB, colA, colA + colB)][] #Analogous for `colD`

     colA   colB   colC
1:   0.00   0.00   0.00
2:   0.00   0.00   0.00
3:   0.00   0.00   0.00
4: 412.99 412.99 412.99
5:  34.43   6.89  41.32
6: 117.36   0.00 117.36
7: 193.05 193.05 193.05
8: 305.22 305.22 305.22