R函数到bind_rows另一个函数的结果

R function to bind_rows the results of another function

我尝试为带有一个或多个列变量的自定义 table 编写一个函数。我用一个变量实现了 tables: .

现在我尝试实现一个函数来为一组变量获取自定义 table,例如均值和多列 table。我的问题是将它们绑定在一起。

这是我拥有的:

library(tidyverse)

## at first some example data:

dv1 <- c(1, 0, 1, 0, 1) # dependent variable 1
dv2 <- c(1, 0, 1, 1, 1) # dependent variable 2
iv1 <- c("m", "f", "f", "m", "m") # independent variable 1
iv2 <- c(30, 40, 30, 40, 40) # independent variable 2
iv3 <- c("b", "c", "b", "a", "a") # ...

DATA <- data_frame(iv1, iv2, iv3, dv1, dv2) # build data frame

# the help function

cross_fun <- function(.data, DV, IV = IVs, fn = ~ mean(.x)) {

   df <- .data   %>% 
      select(all_of({{ IV }}), {{ DV }})  %>% 
    mutate(var = "dv") %>% # here I would like to have the {{ DV }} Argument as values of var, but mutate(var = {{ DV }}) or mutate (var = quote(DV)) does'nt work
    mutate(across(all_of({{IV}}), as.character)) # for using it in "names_from" in pivot_wider

  LIST <- list() # define a list

  for (i in 1:(ncol(df)-2)) { # -1 for the DV
    LIST[[i]] <- df %>% select(i, {{ DV }}, var)
  }
  dt <- purrr::map(
  .x = LIST,
  .f = ~ tidyr::pivot_wider(.x, names_from = 1, values_from = 2, values_fn = fn)
                  ) %>%
    purrr::reduce(left_join, by ="var")

  return(dt)
}

# What I can do
## simple custom table

DATA %>% cross_fun(dv1, IV = c('iv3', 'iv1', 'iv2'))  

## or I use a set (IVs is standard in cross_fun) in multiple tables 
IVs <- c('iv3', 'iv1', 'iv2')

DATA %>% cross_fun(dv2)

## I can change the Variables for the columns and the function
DATA %>% 
  cross_fun(dv2, IV = c('iv3', 'iv1', 'iv2'), fn = ~sum(.x))

## now I try to bind them together in a way, that I can use it later in another function
List_2 <- list()

## I could write it in a List_2 ...
List_2[[1]] <- DATA %>% cross_fun(dv1)

# ... for every variable ...
List_2[[2]] <- DATA %>% cross_fun(dv2)

# ... and bind the rows
List_2 %>% 
  bind_rows()

# here comes my Problem, it doesn't work in my try with for loop ...
for (i in c('dv1', 'dv2')) { 
  Liste2[[i]] <- DATA %>% 
    cross_fun(DATA[[i]])
}

# or with map
DATA %>% 
  map(.x = c(dv1:dv2), .f = ~cross_fun(.x)) %>% # the cross_fun-function for more than one dependent variable
  bind_rows() 

抱歉代码乱七八糟。我是 R 函数的初学者。

问候,本

解决方案

首先,一个答案:purrr::map_dfr自动row-binds它的结果,你应该这样指定它:

map_dfr(c("dv1", "dv2"), cross_fun, .data = DATA)

# # A tibble: 2 x 8
#   var       b     c     a     m     f  `30`  `40`
#   <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 dv        1     0   0.5 0.667   0.5     1 0.333
# 2 dv        1     0   1   1       0.5     1 0.667

批评

您的代码中存在一些问题,其中一些与传递不正确的参数有关。例如,您的 for 循环将 DATA[[i]] 传递给 DV 而不是简单地 i;这会传递来自 DATA[["dv1"]] 的实际值向量,而不仅仅是名称 "dv1",这是您的函数所期望的。

以下解决了这个问题:

List_2 <- list()

# `i` is confusing because the loop iterates over characters, not integers;
# use something like `varname` instead
for (varname in c('dv1', 'dv2')) { 
  List_2[[varname]] <- DATA %>% 
    cross_fun(varname)
}
bind_rows(List_2)

# # A tibble: 2 x 8
#   var       b     c     a     m     f  `30`  `40`
#   <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 dv        1     0   0.5 0.667   0.5     1 0.333
# 2 dv        1     0   1   1       0.5     1 0.667

您的 map 电话有两个问题。第一,您没有将 DATA 传递给 cross_function();您只是将 .x 传递给 .data 参数,而没有传递给其他参数。第二,您试图将 DV 作为符号而不是字符传递。虽然这是可能的,但它很棘手(并且尝试使用 map 遍历符号会使它变得更棘手),并且您的代码未设置为正确处理它。

以下解决了这个问题:

map(c("dv1", "dv2"), .f = ~ cross_fun(DATA, .x)) %>% 
  bind_rows() 

# # A tibble: 2 x 8
#   var       b     c     a     m     f  `30`  `40`
#   <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 dv        1     0   0.5 0.667   0.5     1 0.333
# 2 dv        1     0   1   1       0.5     1 0.667