How can I create colum names in a custom function, pass it to dplyr's select and use purrr's pmap to recycle the custom function?

huangapple go评论59阅读模式
英文:

How can I create colum names in a custom function, pass it to dplyr's select and use purrr's pmap to recycle the custom function?

问题

以下代码应该创建一个名为df_test_purrr的列表,其中包含两个数据框。这两个数据框应该分别包含列vsvs_txt以及amam_txt

作为第一步,函数fn_test接受一个数据框的参数dta和一个列的参数col。直接使用参数dta = df_mtcars, col = expr(vs)调用该函数会创建预期的数据框df_test

# 函数库
library(dplyr)
library(purrr)

# 数据
df_mtcars <- mtcars %>%
  dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ "ABC", T ~ "XYZ"),
                am_txt = dplyr::case_when(am == 1 ~ "TTT", T ~ "BBB"))

# 用于单列的函数
fn_test <- function(dta, col) {
  {{dta}} %>% 
    dplyr::select({{col}}, as.name( paste0({{col}}, "_txt") ))
}

# 单列的结果
df_test <- fn_test( dta = df_mtcars, col = expr(vs) )

# Purrr
fn_test_purrr <- function() {
  purrr::pmap(list(
    list(df_mtcars, df_mtcars),
    list(expr(vs), expr(am))
  ), fn_test )
}

df_test_purrr <- fn_test_purrr()

定义和调用函数fn_test_purrr会出现错误:

Error in `instrument_base_errors()`:
! object 'vs' not found
Caused by error:
! object 'vs' not found
Run `rlang::last_error()` to see where the error occurred.

如何使函数正常工作?

请注意,在我的实际应用程序中,函数fn_test_purrr具有超过两个参数,因此我必须使用purrr的pmap(我猜测)。

英文:

The following code is supposed to create a list, df_test_purrr, with two dataframes. The two dataframes should contain the columns vs, vs_txt and am, am_txt, respectively.

As a first step, the function fn_test takes an argument for a dataframe, dta, and an argument for a column, col. Using the function directly with the argument dta = df_mtcars, col = expr(vs) creates the dataframe df_test as expected.

# Libaries
library(dplyr)
library(purrr)

# Data
df_mtcars &lt;- mtcars %&gt;%
  dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ &quot;ABC&quot;, T ~ &quot;XYZ&quot;),
                am_txt = dplyr::case_when(am == 1 ~ &quot;TTT&quot;, T ~ &quot;BBB&quot;))

# Function for one column
fn_test &lt;- function(dta, col) {
  {{dta}} %&gt;% 
    dplyr::select( {{col}}, as.name( paste0( {{col}}, &quot;_txt&quot;) ) )
}

# Result for one column
df_test &lt;- fn_test( dta = df_mtcars, col = expr(vs) )

# Purrr
fn_test_purrr &lt;- function() {
  purrr::pmap(list(
    list(df_mtcars, df_mtcars),
    list(expr(vs), expr(am))
  ), fn_test )
}

df_test_purrr &lt;- fn_test_purrr()

Defining and calling the function fn_test_purrr gives the error:

Error in `instrument_base_errors()`:
! object &#39;vs&#39; not found
Caused by error:
! object &#39;vs&#39; not found
Run `rlang::last_error()` to see where the error occurred.

How can I make the function work?

Please note that the function fn_test_purrr has more than two arguments in my real-world application such that I must use purrr's pmap (I guess).

答案1

得分: 1

请尝试以下代码:

# 用于单列的函数
fn_test <- function(dta, col) {
  col2 <- paste0(col,'_txt')
  col2 <- col2[col2!='c_txt']
  dta %>%
    dplyr::select( {{col}}, col2) 
}

# 单列的结果
df_test <- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )

# 输出

                    vs am vs_txt am_txt
Mazda RX4            0  1    XYZ    TTT
Mazda RX4 Wag        0  1    XYZ    TTT
Datsun 710           1  1    ABC    TTT
Hornet 4 Drive       1  0    ABC    BBB
Hornet Sportabout    0  0    XYZ    BBB
Valiant              1  0    ABC    BBB
Duster 360           0  0    XYZ    BBB
Merc 240D            1  0    ABC    BBB
Merc 230             1  0    ABC    BBB
Merc 280             1  0    ABC    BBB
Merc 280C            1  0    ABC    BBB
Merc 450SE           0  0    XYZ    BBB
Merc 450SL           0  0    XYZ    BBB
Merc 450SLC          0  0    XYZ    BBB
Cadillac Fleetwood   0  0    XYZ    BBB
Lincoln Continental  0  0    XYZ    BBB
Chrysler Imperial    0  0    XYZ    BBB
Fiat 128             1  1    ABC    TTT
Honda Civic          1  1    ABC    TTT
Toyota Corolla       1  1    ABC    TTT
Toyota Corona        1  0    ABC    BBB
Dodge Challenger     0  0    XYZ    BBB
AMC Javelin          0  0    XYZ    BBB
Camaro Z28           0  0    XYZ    BBB
Pontiac Firebird     0  0    XYZ    BBB
Fiat X1-9            1  1    ABC    TTT
Porsche 914-2        0  1    XYZ    TTT
Lotus Europa         1  1    ABC    TTT
Ford Pantera L       0  1    XYZ    TTT
Ferrari Dino         0  1    XYZ    TTT
Maserati Bora        0  1    XYZ    TTT
Volvo 142E           1  1    ABC    TTT
英文:

Could you please try the below code

# Function for one column
fn_test &lt;- function(dta, col) {
  col2 &lt;- paste0(col,&#39;_txt&#39;)
  col2 &lt;- col2[col2!=&#39;c_txt&#39;]
  dta %&gt;% 
    dplyr::select( {{col}}, col2) 
}

# Result for one column
df_test &lt;- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )

#output

                    vs am vs_txt am_txt
Mazda RX4            0  1    XYZ    TTT
Mazda RX4 Wag        0  1    XYZ    TTT
Datsun 710           1  1    ABC    TTT
Hornet 4 Drive       1  0    ABC    BBB
Hornet Sportabout    0  0    XYZ    BBB
Valiant              1  0    ABC    BBB
Duster 360           0  0    XYZ    BBB
Merc 240D            1  0    ABC    BBB
Merc 230             1  0    ABC    BBB
Merc 280             1  0    ABC    BBB
Merc 280C            1  0    ABC    BBB
Merc 450SE           0  0    XYZ    BBB
Merc 450SL           0  0    XYZ    BBB
Merc 450SLC          0  0    XYZ    BBB
Cadillac Fleetwood   0  0    XYZ    BBB
Lincoln Continental  0  0    XYZ    BBB
Chrysler Imperial    0  0    XYZ    BBB
Fiat 128             1  1    ABC    TTT
Honda Civic          1  1    ABC    TTT
Toyota Corolla       1  1    ABC    TTT
Toyota Corona        1  0    ABC    BBB
Dodge Challenger     0  0    XYZ    BBB
AMC Javelin          0  0    XYZ    BBB
Camaro Z28           0  0    XYZ    BBB
Pontiac Firebird     0  0    XYZ    BBB
Fiat X1-9            1  1    ABC    TTT
Porsche 914-2        0  1    XYZ    TTT
Lotus Europa         1  1    ABC    TTT
Ford Pantera L       0  1    XYZ    TTT
Ferrari Dino         0  1    XYZ    TTT
Maserati Bora        0  1    XYZ    TTT
Volvo 142E           1  1    ABC    TTT

答案2

得分: 1

请检查更新后的代码,该代码返回包含两个数据框的列表。

df_mtcars <- mtcars %>%
  dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ "ABC", T ~ "XYZ"),
                am_txt = dplyr::case_when(am == 1 ~ "TTT", T ~ "BBB"))

fn_test <- function(dta, col) {
  col2 <- paste0(col,'_txt')
  col2 <- col2[col2!='c_txt']

  if (length(col)==1){
    len=1
    col2 <- paste0(col,'_txt')
  } else if(length(col)>1){
    len <- length(col)-1  
  }
  
  my.list <- list()
  
  for(i in 1:len){
  colx <- paste0({{col}})[i+1]
  colx2 <- col2[i]
  dat <- dta %>% 
    dplyr::select( {{colx}}, colx2) 
    
  my.list[[i]] <- dat
  }
  return(my.list)
}

# 一个列的结果
mylist <- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )

df1 <- as.data.frame(mylist[1])
df2 <- as.data.frame(mylist[2])

这是代码的翻译部分,不包括问题的回答。

英文:

Please check updated code which returns the list with 2 dataframes

df_mtcars &lt;- mtcars %&gt;%
  dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ &quot;ABC&quot;, T ~ &quot;XYZ&quot;),
                am_txt = dplyr::case_when(am == 1 ~ &quot;TTT&quot;, T ~ &quot;BBB&quot;))

fn_test &lt;- function(dta, col) {
  col2 &lt;- paste0(col,&#39;_txt&#39;)
  col2 &lt;- col2[col2!=&#39;c_txt&#39;]

  if (length(col)==1){
    len=1
    col2 &lt;- paste0(col,&#39;_txt&#39;)
  } else if(length(col)&gt;1){
    len &lt;- length(col)-1  
  }
  
  my.list &lt;- list()
  
  for(i in 1:len){
  colx &lt;- paste0({{col}})[i+1]
  colx2 &lt;- col2[i]
  dat &lt;- dta %&gt;% 
    dplyr::select( {{colx}}, colx2) 
    
  my.list[[i]] &lt;- dat
  }
  return(my.list)
}

# Result for one column
mylist &lt;- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )

df1 &lt;- as.data.frame(mylist[1])
df2 &lt;- as.data.frame(mylist[2])

答案3

得分: 0

以下是您要翻译的内容:

对于那些感兴趣的人,我提出了一种不同的方法,也适用于我的目的:

library(dplyr)
library(purrr)

数据

df_mtcars <- mtcars %>%
dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ "ABC", T ~ "XYZ"),
am_txt = dplyr::case_when(am == 1 ~ "TTT", T ~ "BBB"))

用于一个列的函数

fn_test <- function(dta, var) {
dta %>%
dplyr::select( {{var}} )
}

函数调用

test <- fn_test(dta = df_mtcars, var = c("vs", "vs_txt"))

Purrr

fn_test_purrr <- function() {
purrr::pmap(
list(
list(df_mtcars, df_mtcars),
list(c("vs", "vs_txt"), c("am", "am_txt"))
), fn_test
)
}

函数调用

test_purrr <- fn_test_purrr()

结果

test_purrr[[1]]
test_purrr[[2]]

英文:

For those who are interested, I came up with a different approach that also works for my purpose:

# Libaries
library(dplyr)
library(purrr)

# Data
df_mtcars &lt;- mtcars %&gt;%
  dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ &quot;ABC&quot;, T ~ &quot;XYZ&quot;),
                am_txt = dplyr::case_when(am == 1 ~ &quot;TTT&quot;, T ~ &quot;BBB&quot;))


# Function for one column
fn_test &lt;- function(dta, var) {
  dta %&gt;% 
    dplyr::select( {{var}} )
}

# Function call
test &lt;- fn_test(dta = df_mtcars, var = c(&quot;vs&quot;, &quot;vs_txt&quot;))

# Purrr
fn_test_purrr &lt;- function() {
  purrr::pmap(
    list(
      list(df_mtcars, df_mtcars),
      list(c(&quot;vs&quot;, &quot;vs_txt&quot;), c(&quot;am&quot;, &quot;am_txt&quot;))
    ), fn_test
  )
}

# Function call
test_purrr &lt;- fn_test_purrr()

# Results
test_purrr[[1]]
test_purrr[[2]]

huangapple
  • 本文由 发表于 2023年6月26日 22:45:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76557763.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定