Henry
Henry

Reputation: 5

Local variables inside R function doesn't work

I need your help. I have a data frame looks like below

   id      home_1     home_2      home_3
1   1 -0.07288651 -1.0946734  0.06310788
2   2  0.27480575 -0.5939264 -0.10267407
3   3 -1.29267610 -1.0765848 -0.96190129
4   4 -0.53468273  0.5315489 -1.36055340
...

I want to create 3 data frames; df1, df2 and df3


Please find the codes below

dummy <- data.frame(id = 1:10,home_1 = rnorm(10),home_2 = rnorm(10),home_3 = rnorm(10))

f <- function(df,param1, param2) {
    c <- paste0(param1, "_", param2);
    print(paste0("Let's sort column ", c))
    df %>% arrange(c) %>% print()  #sort dataframe by column 'home_1/2/3'
}

for (i in 1:3) {
    print(paste0("Index : ",i))
    table <- paste0("df",i)     
    table <- f(dummy,"home",i) # create dataframe with name df1/2/3
}

Problem 1 Then I run my code, the function cannot detect the respective column. The errors inside my function

Error in grouped_df_impl(data, unname(vars), drop) : 
Column `c` is unknown 

the local variable c does exist, but the group_by function cannot detect c.

Does anybody know how to make Column 'c' to be detected by group_by function?

Problem 2 Same problem with my for loop. I want to create a data frame name that is dynamic.

However, this following function table <- f(dummy,"home",i), created a data frame with name 'table' instead of 'df1'.

Can anybody give me a hint on how to resolve these issues? Thank you in advance.

Upvotes: 0

Views: 227

Answers (2)

Athanasia Mowinckel
Athanasia Mowinckel

Reputation: 462

I would use tidyverse's arrange function for this, which is very straight forward.

I'd also use "assign" from base-r to assign a value to a vetor who's name is stored in a string.

library(tidyverse)
for(i in 1:(ncol(dummy)-1)){
  #define the name for the new data
  new = paste0("df",i) 

  #define the same of the column to sort on
  col = paste("home",i,sep="_") 

  # based on the data dummy, arrange the rows according to "col"
  # we need to use "get" because arrange expects bare (unquoted) column names
  tmp = dummy %>% arrange(get(col))
  assign(new, tmp)
 }

Upvotes: 2

chinsoon12
chinsoon12

Reputation: 25225

You can loop through the list of columns and then order by each column

cols <- structure(setdiff(names(dat), "id"), names=setdiff(names(dat), "id"))
lapply(cols, function(x) dat[order(dat[,x]),])

data:

dat <- read.table(text="id      home_1     home_2      home_3
1 -0.07288651 -1.0946734  0.06310788
2  0.27480575 -0.5939264 -0.10267407
3 -1.29267610 -1.0765848 -0.96190129
4 -0.53468273  0.5315489 -1.36055340", header=TRUE)

Upvotes: 1

Related Questions