0

I am struggling to reference columns with a function.

Take the data:

  dat = data.frame(height = c(20, 20, 40, 50, 60, 10), weight = c(100, 200, 300, 200, 140, 240),
               age = c(19, 20, 20, 19, 10, 11))
  Age_list <- c(19)

Take the example:

toy_func <- function(df,list,column){

  for (i in list){
  toy_output <- df[,column == i]
  }

  Return(toy_output)
}

And run:

tst <- toy_func(dat,Age_list,"age")

The output is a dataframe with no variables. I would like to generate an output where the initial dataframe dat has been filtered by ages that equal 19.

The loop is necessary as I plan to iterate through each unique item in the age column. Essentially i am writting a function to partition a dataframe by the unique values in one of its columns.

Thanks in advance, John

4
  • 1
    partitioning a data.frame by it's unique values can be done using the split function. See what happens with split(mtcars, mtcars$gear) Commented Aug 31, 2018 at 13:27
  • toy_output <- df[df[[column]] == i] Commented Aug 31, 2018 at 13:31
  • Don't think this is possible because i want to write a general function and so we can't use $ Commented Aug 31, 2018 at 13:31
  • There is a function to do what you mentioned "...partition a dataframe by the unique values in one of its columns" and it's called split as @phiver mentioned. In your case you can check it with split(dat, dat$age). Is this the output you wanted? Commented Aug 31, 2018 at 13:58

2 Answers 2

2

Using the advice of @phiver, you can try this:

dat = data.frame(height = c(20, 20, 40, 50, 60, 10),
                 weight = c(100, 200, 300, 200, 140, 240),
                 age = c(19, 20, 20, 19, 10, 11))
Age_list <- c(19,20)

for (i in Age_list){
  toy_output <- split(dat,dat$age==i)$`TRUE`
  print(toy_output)
  }

Result:

  height weight age
1     20    100  19
4     50    200  19
  height weight age
2     20    200  20
3     40    300  20

EDIT:

You can do a simple workaround to put it in a function:

toy_func <- function(df,list,x){

for (i in list){
  toy_output <- split(df,df[,x]==i)$`TRUE`
  print(toy_output)
              }
           }

toy_func(dat,Age_list ,3)

  height weight age
1     20    100  19
4     50    200  19
  height weight age
2     20    200  20
3     40    300  20

EDIT2:

And this is going to give you a data.frame with the result, with the i column that tells you which iteration generates each row:

toy_func <- function(df,list,x){
   datalist = list()
        for (i in list){
            toy_output <- data.frame(split(df,df[,3]==i)$`TRUE`)
            toy_output$i <- i
            datalist[[i]] <- toy_output
                       }
   print(do.call(rbind, datalist))
  }

toy_func(dat,Age_list ,3)

  height weight age  i
5     60    140  10 10
2     20    200  20 20
3     40    300  20 20
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @s_t - that works on my toy example. Could you explain the $TRUE`` part. I assume you used that to get around the issues i had with referencing columns names in a function
Because putting an == is going to give the false and the true result of the equation, and you only need the ==TRUE result, so the $ choose the true. You can have a proof doing this split(dat, dat$age==20), that gives you a list as class. Hope this comment and the answer help you.
Hi, sorry i just realized this won't work within the function because of the use of $. The idea was to write a generalized function.
0

You can try

foo <- function(x, y, z) x[ x[[y]] %in% z, ]
foo(dat, "age", c(19, 20))
  height weight age
1     20    100  19
2     20    200  20
3     40    300  20
4     50    200  19

If you need the output as a sorted list you can write

lapply(c(19,20), foo, x=dat, y="age")
[[1]]
  height weight age
1     20    100  19
4     50    200  19

[[2]]
  height weight age
2     20    200  20
3     40    300  20

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.