Jest to kontynuacja mojego poprzedniego pytania Tutaj , który @ronak_shah był wystarczający, aby odpowiedzieć. Przepraszam, ponieważ niektóre z tych informacji mogą być zbędne dla każdego, kto widział ten post, ale zdecyduje najlepiej opublikować nowe pytanie, a nie zmodyfikować poprzednią wersję.

Nadal chciałbym iterować przez przechowywaną listę kolumn i procedur, aby utworzyć N Nowe kolumny na podstawie tej listy. W poniższym przykładzie zaczynamy od 3 kolumn, a, b, c i prostej funkcji, func1.

Ramka danych col_mod Identyfikuje, która kolumna powinna zostać zmieniona, jaki drugi argument do funkcji, który je zmienia, a następnie generuje oświadczenie o wykonaniu funkcji. Każde z tych modyfikacji powinno być dodatkiem do oryginalnej ramki danych, a nie wymianę określonych kolumn. Nowe nazwy tych kolumn powinny być odpowiednio a_new i c_new.

Na dole poniższego reprexa jestem w stanie ręcznie uzyskać mój pożądany wynik, ale jak wcześniej, chciałbym zautomatyzować to za pomocą funkcji mapowania.

Próbuję użyć tego samego podejścia, które zostało dostarczone jako odpowiedź na moje poprzednie pytanie, ale utrzymuję następujący błąd: "Błąd w Get (AS.Character (Fun), Mode =" Funkcja ", Envire = Envire : Nie znaleziono funkcji "FUNC1 (A, 3)" "

Jeśli ktoś może pomóc, byłby bardzo doceniony!

library(tidyverse)

## fake data
dat <- data.frame(a = 1:5,
                  b = 6:10,
                  c = 11:15)

## function
func1 <- function(x, y) {x + y}

## modification list
col_mod <- data.frame("col" = c("a", "c"),
                      "y_val" = c(3, 4),
                      stringsAsFactors = FALSE) %>% 
  mutate(func = paste0("func1(", col, ",", y_val, ")"))

## desired end result
dat %>% 
  mutate(a_new = func1(a, 3),
         c_new = func1(c, 4))

## attempting to generate new columns based on @ronak_shah's answer to my previous
## question but fails to run
dat[paste0(col_mod$col, '_new')] <- Map(function(x, y) match.fun(y)(x), 
                                      dat[col_mod$col], col_mod$func)
r
1
DJC 25 październik 2020, 23:42

1 odpowiedź

Najlepsza odpowiedź

Możemy użyć pmap z purrr, transmute, transmute kolumny oparte na nazwie z "kol" ..1, funkcji z "FUNC" IE {X4}} i "y_val" z ..2, przypisz (:=) wartość do nowej kolumny, tworząc ciąg z paste (lub str_c) i powiązania kolumn do Oryginalny zestaw danych.

library(dplyr)
library(purrr)
library(stringr)
library(tibble)
col_mod$func <- 'func1'
pmap(col_mod, ~ dat %>%
     transmute(!! str_c(..1, "_new") :=
    match.fun(..3)(!! rlang::sym(..1), ..2))) %>% 
   bind_cols(dat, .)

-wynik

#  a  b  c a_new c_new
#1 1  6 11     4    15
#2 2  7 12     5    16
#3 3  8 13     6    17
#4 4  9 14     7    18
#5 5 10 15     8    19

Jeśli chcemy przeanalizować funkcję, użyj parse_expr i eval i.e. Bez zmiany kolumny func - pozostaje jako func1(a, 3) i func1(c, 4)

pmap(col_mod, ~ dat %>%
  transmute(!! str_c(..1, "_new") := 
      eval(rlang::parse_expr(..3)))) %>%
   bind_cols(dat, .)

-wynik

#  a  b  c a_new c_new
#1 1  6 11     4    15
#2 2  7 12     5    16
#3 3  8 13     6    17
#4 4  9 14     7    18
#5 5 10 15     8    19

Lub używając base R z Map

dat[paste0(col_mod$col, '_new')] <-  do.call(Map, c(f = 
   function(x, y, z) eval(parse(text = z), envir = dat), unname(col_mod)))
1
akrun 25 październik 2020, 21:12