2

I am struggling with using dplyrfunctions in own functions. I am closer to understand but still missing full understanding. Here I have df containing type and D10 variables.

df <- data.frame(type = c("KL", "KL", "A", "A", "B", "B", "9999", "-1"), 
                 D10 = rnorm(8, 3, 4))

I want to write a function that in a new column will return M if the type == "KL"; "-1" if the type %in% c(9999, -1) and that will return K for all the other cases. I want the values of 9999, -1, KL to be possible to change when the function is initiated.

My tries i ended with the function that look like this:

klme <- function(dat, met, minusy = c(-1, 9999), Sortnr, type){
  mutate_call <- lazyeval::interp(~ifelse(a %in% met, "M", ifelse(a %in% minusy, "-1", "K")), a = as.name(Sortnr))
  dat %>% mutate_(.dots = setNames(list(mutate_call), type))
}

klme(df, c("KL"), minusy = c(-1, 9999), "Sortnr", "typ")

that return only K in the typ column while I'd like to obtain output like this:

  type        D10 type.1
1   KL -5.3210620      M
2   KL  4.4832414      M
3    A -5.3979886      K
4    A  2.7933964      K
5    B -0.9602293      K
6    B  4.5097305      K
7 9999 -3.9650796     -1
8   -1  5.2700609     -1
Axeman
  • 32,068
  • 8
  • 81
  • 94
Mateusz1981
  • 1,817
  • 17
  • 33
  • 1
    https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html – Haboryme Nov 23 '16 at 07:26
  • link does not work and anyway I guess I read it and finish up with the function that I presented – Mateusz1981 Nov 23 '16 at 07:28
  • 1
    you have to pass `Sortnr = "type"` to your function, otherwise your result will always be `K` – wici Nov 23 '16 at 07:40
  • Why not just `df$type.1 <- c('K','-1','M')[1 + (df$type %in% c('9999','-1')) + 2*(df$type == 'KL')]` or with a nested `ifelse`: `df$type.1 <- ifelse(df$type %in% c('9999','-1'), '-1', ifelse(df$type == 'KL', 'M', 'K'))`? – Jaap Nov 23 '16 at 08:02
  • I want to have a function for which I will be able to change values `KL`, `M` `K` to ex `S`, `T` ect. I do not want to copy all chains and change in a new place – Mateusz1981 Nov 23 '16 at 08:06
  • @Mateusz1981 did my comment solve your problem? Just to clarify your function call should look like this `klme(df, c("KL"), minusy = c(-1, 9999), Sortnr = "type", "typ")` because your data has no column named `"Sortnr"` – wici Nov 23 '16 at 08:36

2 Answers2

3

I believe you are looking for this, remember that you need to interp all values that are variable (also @wici was right that your call to klme should not have Sortnr since that is not a column in df):

df <- data.frame(type = c("KL", "KL", "A", "A", "B", "B", "9999", "-1"), 
                 D10 = rnorm(8, 3, 4))

klme <- function(dat, met, minusy = c(-1, 9999), Sortnr, type){
  mutate_call <- lazyeval::interp(~ifelse(a %in% y, "M", 
                                          ifelse(a %in% z, "-1", "K")),
                                  a = as.name(Sortnr),
                                  y = met,
                                  z = minusy)
  dat %>% mutate_(.dots = setNames(list(mutate_call), type))
}

klme(df, c("KL"), minusy = c('-1', '9999'), "type", "typ")
  type        D10 typ
1   KL  6.4760905   M
2   KL  7.5196368   M
3    A  2.2588101   K
4    A  1.4910878   K
5    B -0.3357310   K
6    B  1.9693856   K
7 9999 -0.3820483  -1
8   -1  4.5595150  -1
Axeman
  • 32,068
  • 8
  • 81
  • 94
-1

You can you map from purrr as follows:

library(dplyr)
library(purrr)

Define a function to check your conditions:

GetType <- function(x)
{
      if(x=="KL")  "M"
        else if(x %in% c(9999,-1) ) "-1"
        else "K"
}

Then use map as follows, this takes type from each row, pass it to GetType function and return the value in the new column:

df <- df %>% 
        mutate(type.1=map_chr(type,GetType))

> df
  type        D10 type.1
1   KL  3.0820944      M
2   KL  8.0126703      M
3    A  8.0629672      K
4    A  5.8460856      K
5    B  0.6803590      K
6    B -1.1148491      K
7 9999 -0.4981576     -1
8   -1  1.0648742     -1

EDIT In principal you can also pass the values you want to compare with to the functions:

val <- list("KL",c(9999,1))

GetType <- function(x,y)

{
         if(x==y[[1]])  "M"
        else if(x %in% y[[2]] ) "-1"
        else "K"
}


> GetType(df$type[1],val)
[1] "M"
OmaymaS
  • 1,671
  • 1
  • 14
  • 18
  • it is not what I wanted, I do not want to make Changes inside a function whenever I run it. i rather want to have functions arguments are possible to change – Mateusz1981 Nov 23 '16 at 08:14
  • Aha, in principle you can pass the values you want as in the edited solution. – OmaymaS Nov 23 '16 at 08:53