0

I'm writing a For-loopto mutate columns k_et'm' with dynamic names. k_et did not exist before. b001 b002 b003 ... b012 are 12 variables that are already in the dataframe.

b001 b002 b003 ... b012
-2    2    0   ...   1
-1    1    0   ...   0
 1    1   -1   ...  -2

I put them into a dataframe called b. (But it causes that I generate them again. I feel like it's redundant but cannot think of any other way.)

month <- c("001","002","003","004","005","006","007","008","009","010","011","012")

for(m in 1:length(month)) {
  b <- c(paste0("b",m))
  k_et[m] <- paste0("k_et",month[m]) 
  df[,k_et[m]] <- ifelse(b[m]==1, 1, 0)
}

I expect to see:

b001 b002 b003 ... k_et001 k_et002 k_et003
-2    2    0   ...   0       0        0    
-1    1    0   ...   0       1        0
 1    1   -1   ...   1       1        0

However, all my k_et results are 0. What is the problem?

MicL
  • 67
  • 1
  • 8
  • Can you make your example reproducible by sharing a small sample of `monat`? And `df`? And `b`? – Gregor Thomas Jan 18 '22 at 15:36
  • 2
    Assuming `monat` and `month` are the same object, `paste` is vectorized, so you can use `k_et <- paste0("k_et", monat)` before the loop, you don't need to put that inside the loop. If `b` is a data frame, then you might need to use `b[[m]]` instead of `b[m]`, but hard to tell without a reproducible example. – Gregor Thomas Jan 18 '22 at 15:39
  • Yes, you are right. I edited my question and hope this will help. – MicL Jan 18 '22 at 15:55
  • I tried b[[m]] and moved the k_et <- paste0("k_et", monat) before the loop, but the result is the same. – MicL Jan 18 '22 at 16:03
  • 1
    So, you create `b` by pasting together `b` and `m`, so `b` looks like `"b001", "b002"`, etc. These are not number and they never equal `1`, so `b[m]==1` is always FALSE and your result is always 0. I'm not sure what you intend, but the all-0 result makes sense based on your code. – Gregor Thomas Jan 18 '22 at 16:07
  • I see! Then how can I compare the value of ```"b001","b002"``` with 1? I was thinking somthing like ```mutate(k_et001 = ifelse( b001==1, 1, 0))```. – MicL Jan 18 '22 at 16:09
  • I mean, how do you want to compare it to 1? What result do you expect? Exaggerating, but it feels a little like "How do I compare 'dog' to 17?" – Gregor Thomas Jan 18 '22 at 16:11
  • 1
    OH, I see, your "b###" are column names from `df`. You need to tell R that. `ifelse(df[[ b[m] ]]==1, 1, 0)` – Gregor Thomas Jan 18 '22 at 16:13
  • Ahhhh yes, I understand now! Now it works. Thank you! Just one side question, why there are two brackets instead of one out of b[m]? – MicL Jan 18 '22 at 16:18
  • When you have a data frame `df`, `df[[1]]` is a vector (the first column), `df[1]` is a 1-column data frame. When you want a single column `[[` is safer, as some functions won't work on data frames. [See this FAQ for more details](https://stackoverflow.com/q/1169456/903061) – Gregor Thomas Jan 18 '22 at 16:20

1 Answers1

0

You don't need a loop for this. Do it all at once.

## get the values. ifelse() keeps the dimensions
results = ifelse(df == 1, 1, 0)
## fix the names, replacing "b" with "k_et"
colnames(results) = sub(pattern = "b", replacement = "k_et", x = colnames(results))
## stick them together
df = cbind(df, results)
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294