Мутировать по условию со многими столбцами, каждый из которых имеет разные настройки - PullRequest
0 голосов
/ 16 ноября 2018

Я искал, но не нашел, как сделать простой if для многих столбцов в dplyr.

У меня есть этот код (он работает):

library(dplyr)
library(magrittr)
data("PlantGrowth")
PlantGrowth %>% mutate (
  a=if_else(group=="ctrl", weight*2, weight*100),
  b=if_else(group=="ctrl", weight*1,5, weight/100),
  c=if_else(group=="ctrl", weight*4, weight*100),
  d=if_else(group=="ctrl", weight*5, weight/1000)
)

И я бы не хотел повторять это условие. Примерно так:

PlantGrowth %>% mutate_if_foo (
  group=="ctrl",{
   a=weight*2,
   b=weight*1,5,
   c=weight*4,
   d=weight*5
  }
)%>% mutate_if_foo (
  group!="ctrl",{
   a=weight*100,
   b=weight/100),
   c=weight*100),
   d=weight/1000)
  }
)

Я нашел много ответов на mutate_if, mutate_all, mutate_at, case_when, но они не отвечают на мой вопрос.

Пожалуйста, используйте dplyr / tidyverse.

Заранее спасибо

EDIT

Я пытался из идеи @Rohit_das о функциях.

mtcars %>% ( function(df) { 
  if (df$am==1){
    df%>% mutate(
      a=df$mpg*3,
      b=df$cyl*10) 
   }else{ 
     df%>% mutate(
      a=df$disp*300,
      d=df$cyl*1000) 
   }
}) 

но у меня есть предупреждение:

In if (df$am == 1) { : 
the condition has length > 1 
and only the first element will be used

Ответы [ 3 ]

0 голосов
/ 16 ноября 2018

Я думаю, что нашел аккуратное решение с мурлыканием. Он принимает фрейм данных входных данных, а затем динамически присваивает имена новым столбцам a:d с новыми входными данными для каждого столбца. В первом столбце будут использоваться x = 2, y = 100 и z = "a", а затем следующий ряд и т. Д. Крутая вещь с таким функциональным программированием, это то, что его очень легко масштабировать.

library(tidyverse)

iterate <- tibble(x = c(2, 1.5, 4, 5),
                  y = c(100, 1/100, 100, 1/1000),
                  z = c("a", "b", "c", "d"))

fun <- function(x, y, z) {
  PlantGrowth %>% 
    mutate(!!z := if_else(group == "ctrl", weight * x, weight * y)) %>% 
    select(3)
}

PlantGrowth %>% 
  bind_cols(
    pmap_dfc(iterate, fun)
    ) %>% 
  as_tibble

Что дает вам тот же самый df:

# A tibble: 30 x 6
   weight group     a     b     c     d
    <dbl> <fct> <dbl> <dbl> <dbl> <dbl>
 1   4.17 ctrl   8.34  6.26  16.7  20.8
 2   5.58 ctrl  11.2   8.37  22.3  27.9
 3   5.18 ctrl  10.4   7.77  20.7  25.9
 4   6.11 ctrl  12.2   9.17  24.4  30.6
 5   4.5  ctrl   9     6.75  18    22.5
0 голосов
/ 19 ноября 2018

Я думаю, что нашел ответ.Я тестировал на mtcars.Я еще не тестировал свой реальный код.

Прокомментируйте, пожалуйста, если я считаю, что я ошибаюсь в концепции.

Условия фильтров должны быть исключительными, иначе я возьму дубликатлинии.

        library(dplyr)
        library(magrittr)
        library(tibble) # only if necessary to preserve rownames
        mtcars %>% ( function(df) { 
                rbind(
                    (df 
                     %>% tibble::rownames_to_column(.) %>%tibble::rowid_to_column(.)  # to preserve rownames
                     %>%dplyr::filter(am==1) 
                     %>%dplyr::mutate(
                        a=mpg*3,
                        b=cyl*10,d=NA)),
                    (df 
                     %>% tibble::rownames_to_column(.) %>%tibble::rowid_to_column(.)  # to preserve rownames
                     %>%dplyr::filter(am!=1) 
                     %>%dplyr::mutate(
                      a=disp*3,
                      d=cyl*100,b=NA))
                )
        })     %>%arrange(rowid)
0 голосов
/ 16 ноября 2018

Не уверен, что я понимаю проблему здесь. Если вы просто хотите уменьшить детализацию кода, просто создайте пользовательскую функцию

customif = function(x,y) { 
   if_else(group=="ctrl", weight*x, weight*y)
}

тогда вы можете вызвать эту функцию в вашем мутировании как

PlantGrowth %>% mutate (
  a=customif(2,100),
  b=customif(1,5, 1/100),
  c=customif(4, 100),
  d=customif(5, 1/1000)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...