0

I want to subtract one column from another and create a new one using the corresponding suffix in the first column. I have approx 50 columns I can do it "manually" as follows...

df$new1 <- df$col_a1 - df$col_b1 
df$new2 <- df$col_a2 - df$col_b2

What is the easiest way to create a loop that does the job for me?

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • So you have a pattern with the names right? and the number is the same on both the left and right side. So as you note by your tag a for loop might be one way to do this and you could use paste0() to create the names. Have you tried something lke that? It's not necessarily the "r way" but it would help to show what you have tried. Not that you can use the df[name] notation. – Elin Nov 23 '19 at 00:47
  • You could probably get somewhere by reshaping your data. Can you add a [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)? – camille Nov 23 '19 at 01:33
  • Thanks for the response, see reproducible data below. Short explanation–I have responses to 20 questions/statements and 20 responses for matching confidence levels on these questions/statements. Now I want to calculate if participants were over or under-confident (confidence - actual response) – Marcus Lithander Nov 24 '19 at 03:54
  • `stat <- matrix(rnorm(100, 50, 10), ncol=20, nrow = 100)` `conf <- matrix(rnorm(100, 50, 10), ncol=20, nrow = 100)` `colnames(stat) <- paste0("statement", 1:20)` `colnames(conf) <- paste0("confidence", 1:20)` `accu <- as.data.frame(cbind(stat, conf))` – Marcus Lithander Nov 24 '19 at 03:55

1 Answers1

0

We can use grep to identify columns which has "a" and "b" in it and subtract them directly.

a_cols <- grep("col_a", names(df))
b_cols <- grep("col_b", names(df))
df[paste0("new", seq_along(a_cols))] <- df[a_cols] - df[b_cols]
df

#  col_a1 col_a2 col_b1 col_b2 new1 new2
#1     10     15      1      5    9   10
#2      9     14      2      6    7    8
#3      8     13      3      7    5    6
#4      7     12      4      8    3    4
#5      6     11      5      9    1    2
#6      5     10      6     10   -1    0

data

Tested on this data

df <- data.frame(col_a1 = 10:5, col_a2 = 15:10, col_b1 = 1:6, col_b2 = 5:10)
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Excellent, thanks! Here is my final code: `stat <- matrix(rnorm(100, 50, 10), ncol=20, nrow = 100 ) conf <- matrix(rnorm(100, 50, 10), ncol=20, nrow = 100 ) colnames(stat) <- paste0("statement", 1:20) colnames(conf) <- paste0("confidence", 1:20) accu <- as.data.frame(cbind(stat, conf)) #grab "statement"- and "confidence" columns stat_col <- (grep("statement",names(accu))) conf_col <- (grep("confidence", names(accu))) accu[paste0("Acc", seq_along(stat_col))] <- accu[,conf_col] - accu[,stat_col]` – Marcus Lithander Nov 24 '19 at 04:05