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评论96阅读模式
英文:

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

  1. # 函数库
  2. library(dplyr)
  3. library(purrr)
  4. # 数据
  5. df_mtcars <- mtcars %>%
  6. dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ "ABC", T ~ "XYZ"),
  7. am_txt = dplyr::case_when(am == 1 ~ "TTT", T ~ "BBB"))
  8. # 用于单列的函数
  9. fn_test <- function(dta, col) {
  10. {{dta}} %>%
  11. dplyr::select({{col}}, as.name( paste0({{col}}, "_txt") ))
  12. }
  13. # 单列的结果
  14. df_test <- fn_test( dta = df_mtcars, col = expr(vs) )
  15. # Purrr
  16. fn_test_purrr <- function() {
  17. purrr::pmap(list(
  18. list(df_mtcars, df_mtcars),
  19. list(expr(vs), expr(am))
  20. ), fn_test )
  21. }
  22. df_test_purrr <- fn_test_purrr()

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

  1. Error in `instrument_base_errors()`:
  2. ! object 'vs' not found
  3. Caused by error:
  4. ! object 'vs' not found
  5. 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.

  1. # Libaries
  2. library(dplyr)
  3. library(purrr)
  4. # Data
  5. df_mtcars &lt;- mtcars %&gt;%
  6. dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ &quot;ABC&quot;, T ~ &quot;XYZ&quot;),
  7. am_txt = dplyr::case_when(am == 1 ~ &quot;TTT&quot;, T ~ &quot;BBB&quot;))
  8. # Function for one column
  9. fn_test &lt;- function(dta, col) {
  10. {{dta}} %&gt;%
  11. dplyr::select( {{col}}, as.name( paste0( {{col}}, &quot;_txt&quot;) ) )
  12. }
  13. # Result for one column
  14. df_test &lt;- fn_test( dta = df_mtcars, col = expr(vs) )
  15. # Purrr
  16. fn_test_purrr &lt;- function() {
  17. purrr::pmap(list(
  18. list(df_mtcars, df_mtcars),
  19. list(expr(vs), expr(am))
  20. ), fn_test )
  21. }
  22. df_test_purrr &lt;- fn_test_purrr()

Defining and calling the function fn_test_purrr gives the error:

  1. Error in `instrument_base_errors()`:
  2. ! object &#39;vs&#39; not found
  3. Caused by error:
  4. ! object &#39;vs&#39; not found
  5. 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

请尝试以下代码:

  1. # 用于单列的函数
  2. fn_test <- function(dta, col) {
  3. col2 <- paste0(col,'_txt')
  4. col2 <- col2[col2!='c_txt']
  5. dta %>%
  6. dplyr::select( {{col}}, col2)
  7. }
  8. # 单列的结果
  9. df_test <- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )
  10. # 输出
  11. vs am vs_txt am_txt
  12. Mazda RX4 0 1 XYZ TTT
  13. Mazda RX4 Wag 0 1 XYZ TTT
  14. Datsun 710 1 1 ABC TTT
  15. Hornet 4 Drive 1 0 ABC BBB
  16. Hornet Sportabout 0 0 XYZ BBB
  17. Valiant 1 0 ABC BBB
  18. Duster 360 0 0 XYZ BBB
  19. Merc 240D 1 0 ABC BBB
  20. Merc 230 1 0 ABC BBB
  21. Merc 280 1 0 ABC BBB
  22. Merc 280C 1 0 ABC BBB
  23. Merc 450SE 0 0 XYZ BBB
  24. Merc 450SL 0 0 XYZ BBB
  25. Merc 450SLC 0 0 XYZ BBB
  26. Cadillac Fleetwood 0 0 XYZ BBB
  27. Lincoln Continental 0 0 XYZ BBB
  28. Chrysler Imperial 0 0 XYZ BBB
  29. Fiat 128 1 1 ABC TTT
  30. Honda Civic 1 1 ABC TTT
  31. Toyota Corolla 1 1 ABC TTT
  32. Toyota Corona 1 0 ABC BBB
  33. Dodge Challenger 0 0 XYZ BBB
  34. AMC Javelin 0 0 XYZ BBB
  35. Camaro Z28 0 0 XYZ BBB
  36. Pontiac Firebird 0 0 XYZ BBB
  37. Fiat X1-9 1 1 ABC TTT
  38. Porsche 914-2 0 1 XYZ TTT
  39. Lotus Europa 1 1 ABC TTT
  40. Ford Pantera L 0 1 XYZ TTT
  41. Ferrari Dino 0 1 XYZ TTT
  42. Maserati Bora 0 1 XYZ TTT
  43. Volvo 142E 1 1 ABC TTT
英文:

Could you please try the below code

  1. # Function for one column
  2. fn_test &lt;- function(dta, col) {
  3. col2 &lt;- paste0(col,&#39;_txt&#39;)
  4. col2 &lt;- col2[col2!=&#39;c_txt&#39;]
  5. dta %&gt;%
  6. dplyr::select( {{col}}, col2)
  7. }
  8. # Result for one column
  9. df_test &lt;- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )
  10. #output
  11. vs am vs_txt am_txt
  12. Mazda RX4 0 1 XYZ TTT
  13. Mazda RX4 Wag 0 1 XYZ TTT
  14. Datsun 710 1 1 ABC TTT
  15. Hornet 4 Drive 1 0 ABC BBB
  16. Hornet Sportabout 0 0 XYZ BBB
  17. Valiant 1 0 ABC BBB
  18. Duster 360 0 0 XYZ BBB
  19. Merc 240D 1 0 ABC BBB
  20. Merc 230 1 0 ABC BBB
  21. Merc 280 1 0 ABC BBB
  22. Merc 280C 1 0 ABC BBB
  23. Merc 450SE 0 0 XYZ BBB
  24. Merc 450SL 0 0 XYZ BBB
  25. Merc 450SLC 0 0 XYZ BBB
  26. Cadillac Fleetwood 0 0 XYZ BBB
  27. Lincoln Continental 0 0 XYZ BBB
  28. Chrysler Imperial 0 0 XYZ BBB
  29. Fiat 128 1 1 ABC TTT
  30. Honda Civic 1 1 ABC TTT
  31. Toyota Corolla 1 1 ABC TTT
  32. Toyota Corona 1 0 ABC BBB
  33. Dodge Challenger 0 0 XYZ BBB
  34. AMC Javelin 0 0 XYZ BBB
  35. Camaro Z28 0 0 XYZ BBB
  36. Pontiac Firebird 0 0 XYZ BBB
  37. Fiat X1-9 1 1 ABC TTT
  38. Porsche 914-2 0 1 XYZ TTT
  39. Lotus Europa 1 1 ABC TTT
  40. Ford Pantera L 0 1 XYZ TTT
  41. Ferrari Dino 0 1 XYZ TTT
  42. Maserati Bora 0 1 XYZ TTT
  43. Volvo 142E 1 1 ABC TTT

答案2

得分: 1

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

  1. df_mtcars <- mtcars %>%
  2. dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ "ABC", T ~ "XYZ"),
  3. am_txt = dplyr::case_when(am == 1 ~ "TTT", T ~ "BBB"))
  4. fn_test <- function(dta, col) {
  5. col2 <- paste0(col,'_txt')
  6. col2 <- col2[col2!='c_txt']
  7. if (length(col)==1){
  8. len=1
  9. col2 <- paste0(col,'_txt')
  10. } else if(length(col)>1){
  11. len <- length(col)-1
  12. }
  13. my.list <- list()
  14. for(i in 1:len){
  15. colx <- paste0({{col}})[i+1]
  16. colx2 <- col2[i]
  17. dat <- dta %>%
  18. dplyr::select( {{colx}}, colx2)
  19. my.list[[i]] <- dat
  20. }
  21. return(my.list)
  22. }
  23. # 一个列的结果
  24. mylist <- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )
  25. df1 <- as.data.frame(mylist[1])
  26. df2 <- as.data.frame(mylist[2])

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

英文:

Please check updated code which returns the list with 2 dataframes

  1. df_mtcars &lt;- mtcars %&gt;%
  2. dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ &quot;ABC&quot;, T ~ &quot;XYZ&quot;),
  3. am_txt = dplyr::case_when(am == 1 ~ &quot;TTT&quot;, T ~ &quot;BBB&quot;))
  4. fn_test &lt;- function(dta, col) {
  5. col2 &lt;- paste0(col,&#39;_txt&#39;)
  6. col2 &lt;- col2[col2!=&#39;c_txt&#39;]
  7. if (length(col)==1){
  8. len=1
  9. col2 &lt;- paste0(col,&#39;_txt&#39;)
  10. } else if(length(col)&gt;1){
  11. len &lt;- length(col)-1
  12. }
  13. my.list &lt;- list()
  14. for(i in 1:len){
  15. colx &lt;- paste0({{col}})[i+1]
  16. colx2 &lt;- col2[i]
  17. dat &lt;- dta %&gt;%
  18. dplyr::select( {{colx}}, colx2)
  19. my.list[[i]] &lt;- dat
  20. }
  21. return(my.list)
  22. }
  23. # Result for one column
  24. mylist &lt;- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )
  25. df1 &lt;- as.data.frame(mylist[1])
  26. 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:

  1. # Libaries
  2. library(dplyr)
  3. library(purrr)
  4. # Data
  5. df_mtcars &lt;- mtcars %&gt;%
  6. dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ &quot;ABC&quot;, T ~ &quot;XYZ&quot;),
  7. am_txt = dplyr::case_when(am == 1 ~ &quot;TTT&quot;, T ~ &quot;BBB&quot;))
  8. # Function for one column
  9. fn_test &lt;- function(dta, var) {
  10. dta %&gt;%
  11. dplyr::select( {{var}} )
  12. }
  13. # Function call
  14. test &lt;- fn_test(dta = df_mtcars, var = c(&quot;vs&quot;, &quot;vs_txt&quot;))
  15. # Purrr
  16. fn_test_purrr &lt;- function() {
  17. purrr::pmap(
  18. list(
  19. list(df_mtcars, df_mtcars),
  20. list(c(&quot;vs&quot;, &quot;vs_txt&quot;), c(&quot;am&quot;, &quot;am_txt&quot;))
  21. ), fn_test
  22. )
  23. }
  24. # Function call
  25. test_purrr &lt;- fn_test_purrr()
  26. # Results
  27. test_purrr[[1]]
  28. 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:

确定