Home > Software design >  it works in a loop, but not when the for loop is in a funciton, why?
it works in a loop, but not when the for loop is in a funciton, why?

Time:11-19

I want to make a function to change name of a vector when it matches another vector. When I write it as a for loop it works, but I want to put it in a function, then it doesnt work, what am I doing wrong? Thanks!

In a for loop:

df <- 1:5
df2 <- data.frame(id=3:7, name=LETTERS[1:5]) 

for(i in 1:length(df)) {
  for(j in 1:nrow(df2)){
    if(df[i]==df2$id[j]){
      df[i] <- df2$name[j]
    }
  }
}
df
#> [1] "1" "2" "A" "B" "C"

I want it in a function, it doesnt work:

match <- function(df,df2){
  for(i in 1:length(df)) {
    for(j in 1:nrow(df2)){
      if(df[i]==df2$id[j]){
        df[i] <- df2$name[j]
      }
    }
  }
}
df <- match(df,df2)
df
#> NULL

CodePudding user response:

You forgot to return the df inside the function.

match <- function(df,df2){
  for(i in 1:length(df)) {
    for(j in 1:nrow(df2)){
      if(df[i]==df2$id[j]){
        df[i] <- df2$name[j]
      }
    }
  }
  df
}
df <- 1:5
df2 <-data.frame(id=3:7, name=LETTERS[1:5]) 
df <- match(df, df2)
df
#> [1] "1" "2" "A" "B" "C"

Created on 2021-11-18 by the reprex package (v2.0.1)

CodePudding user response:

As R is a vectorized language, loops are not necessary here. What about using the buil-in match:

tmp <- df2$name[match(df, df2$id)]
df <- ifelse(is.na(tmp), df, tmp)
df
# [1] "1" "2" "A" "B" "C"

This can of course be wrapped by a function.

As an alternative, one can also use a "join" function, e.g. left_join from package dplyr.

  •  Tags:  
  • r
  • Related