1

Let's assume I have this dataframe:

df <- data.frame(A = letters[1:5],
                B = letters[6:10],
                stringsAsFactors = FALSE)
  A B
1 a f
2 b g
3 c h
4 d i
5 e j

Where I'm looking for this output:

  A B
1 e j
2 d i
3 c h
4 b g
5 a f

With this function:

f_Order <- function(df){
  df$Order <- as.integer(row.names(df))
  df <- arrange(df, desc(Order))[,c("A","B")]
}

Though the function above doesn't work, the code inside the function works perfectly:

df$Order <- as.integer(row.names(df))
df <- arrange(df, desc(Order))[,c("A","B")]
> x
  A B
1 e j
2 d i
3 c h
4 b g
5 a f

Why? How do I make the function work?

EDIT:

To clarify, the problem statement is not to change the order of the df, but to make the function f_Order to work. The code does what I want, but it doesn't what I want inside that function. I need to know why, and how I can make the function to work.

EDIT2:

This is exactly the code I'm running, and still doesn't work any of the solutions.

x <- data.frame(A = letters[1:5],
                B = letters[6:10],
                stringsAsFactors = FALSE)

f_Order <- function(df){
  df$Order <- as.integer(row.names(df))
  df <- arrange(df, desc(Order))
  return(df)
}
f_Order(x)
Jaap
  • 81,064
  • 34
  • 182
  • 193
Chris
  • 2,019
  • 5
  • 22
  • 67
  • Possible duplicate of [How to use dplyr programming syntax to create and evaluate variable names](https://stackoverflow.com/questions/53859015/how-to-use-dplyr-programming-syntax-to-create-and-evaluate-variable-names) – NelsonGon Apr 17 '19 at 14:56
  • I don't see how that question is at least similar to mine @NelsonGon – Chris Apr 17 '19 at 15:01
  • `dplyr` based functions use `quasiquotation` which is what is used in the answers to the above question. – NelsonGon Apr 17 '19 at 15:02
  • The expected output is the df starting with `e` and `j`. I put an example in the question. My second edit gives you the desired output? Because it doesn't give it to me the desired output. – Chris Apr 17 '19 at 15:21

2 Answers2

4

What if you have a return() at the end of your function? Something like this:

f_Order <- function(df){
  df$Order <- as.integer(row.names(df))
  df <- arrange(df, desc(Order))[,c("A","B")]
  return(df)
}

Basically if you have stuff happening in a function, you need to return it at the end if you want there to be an output. Otherwise it just...does it inside the function, but not in the wider environment, and then doesn't show you anything.

Output:

> f_Order(df)
  A B
1 e j
2 d i
3 c h
4 b g
5 a f

If you want to update df, then run df <- f_Order(df).

Jaccar
  • 1,720
  • 17
  • 46
  • I understand it. I just need the changes (not the return). But I still don't get why it works for you and not for me. – Chris Apr 17 '19 at 15:08
  • 3
    That's because in your function you don't return a value, instead, you just assign to a variable `df`, which will live only inside the function, not outside. With `return(df)` you will return an object that will live outside of the function. – RLave Apr 17 '19 at 15:11
  • 1
    If you have the `return()` in there then you can do something like `df <- f_Order(df)` to make the changes stick. – Jaccar Apr 17 '19 at 15:11
  • 1
    Instead of `f_Order(x)`, have `x <- f_Order(x)`. That will change `x` to be the version with the function applied. – Jaccar Apr 17 '19 at 15:20
  • Lol. It was so simple. And I was wondering if I would have to update the R version haha. Thanks! – Chris Apr 17 '19 at 15:23
  • 1
    @RLave - The function as they had it did return a value. It did so invisibly though so would either need to explicitly printed or stored and then viewed later. – Dason Apr 17 '19 at 18:22
2

Continuing with dplyr:

f_Order <- function(df){
  #df$Order <- as.integer(row.names(df))
  df %>% 
    mutate(Order=row.names(.)) %>% 
  arrange(desc(Order))
}

If we don't want to keep Order:

 f_Order <- function(df){

      df %>% 
         arrange(desc(row.names(.)))
    }

Result:

f_Order(df)
   A B
1 e j
2 d i
3 c h
4 b g
5 a f
NelsonGon
  • 13,015
  • 7
  • 27
  • 57