0

I am trying to improve my R codes and I wonder how I could loop over these variables/a problem like this to reduce the length of the code? I assume there must be a very simple solution, but somehow I can not figure it out.

df$zx1 <- with(df, var1*(x1/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx2 <- with(df, var1*(x2/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx3 <- with(df, var1*(x3/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx4 <- with(df, var1*(x4/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx5 <- with(df, var1*(x5/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx6 <- with(df, var1*(x6/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx7 <- with(df, var1*(x7/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx8 <- with(df, var1*(x8/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx9 <- with(df, var1*(x9/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))
df$zx10 <- with(df, var1*(x10/(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10)))

Any inputs are highly appreciated!

Kat
  • 13
  • 2
  • 1
    These all 10 lines could be replaced by something like `df[paste0("zx", 1:10)] <- df$var1 * df[-1] / rowSums(df[-1])` (assuming `var1` is the first column and all the rest are `x1:x10`). Otherwise, please provide an example of your data – David Arenburg Jul 28 '20 at 09:24

2 Answers2

1

Using dplyr you can try :

library(dplyr)
df <- data.frame(var1 = 1:5, x1 = 2:6, x2 = 3:7, x3 = 1:5)

df %>%
  mutate(row_sum = rowSums(.[-1])) %>%
  mutate(across(starts_with('x'), ~var1 * ./row_sum, .names  = 'zx_{col}'))
  #For dplyr < 1.0.0
  #mutate_at(vars(starts_with('x')), list(zx = ~var1 * ./row_sum))


#  var1 x1 x2 x3 row_sum     zx_x1     zx_x2     zx_x3
#1    1  2  3  1       6 0.3333333 0.5000000 0.1666667
#2    2  3  4  2       9 0.6666667 0.8888889 0.4444444
#3    3  4  5  3      12 1.0000000 1.2500000 0.7500000
#4    4  5  6  4      15 1.3333333 1.6000000 1.0666667
#5    5  6  7  5      18 1.6666667 1.9444444 1.3888889
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • your expertise needed since due to some issue im blocked here to ask https://stackoverflow.com/questions/63138416/saving-tidypmc-output-which-forms-a-list-object-and-saving-it-into-individual-fi/63142069#63142069 – kcm Jul 28 '20 at 22:12
0

Assuming var1 is the first variable in df, and x1, x2, x3 etc are all the others. That that should do it:

for(i in 1:10){
 df[ , paste0("zx", i)] <- df$var1 * df[ , paste0("x", i)]/rowSums(df[2:11])
}
Vesnič
  • 365
  • 5
  • 17
  • Many thanks for your quick answer. Somehow, I get the error message "non-numeric argument to binary operator" - I tried it out with a toy example and it works - however, with my original dataset it does not. I checked for NAs and class() of the variables and it all seems ok (no NAs all numeric) - Do you have any idea about this error message or what else I could check? – Kat Jul 28 '20 at 10:12
  • Check if your variables are numeric. This error usually comes up when you are trying to use operators on non-numeric variables (example: ```1 + one``` will give you this error) – Vesnič Jul 28 '20 at 10:17
  • I found the error - my data was not a data.frame... but otherwise your solution worked like a charm! Many thanks :) – Kat Jul 28 '20 at 13:03