创建新列:从第一个现有列创建,如果没有现有列,则为NA。

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

R data frame create new column from first existing column or NA if no existing columns

问题

以下是代码部分的翻译:

  1. library(dplyr, warn.conflicts = FALSE)
  2. #> 警告:package 'dplyr' 是在 R 版本 4.2.3 下构建的
  3. # `dplyr::coalesce` 返回第一个非缺失值,但这些列必须存在
  4. return_exist_var <- function(.var1, .var2, .fill = NA, .data) {
  5. # 从 magrittr::%>% 获取 .
  6. .data <- get(".", parent.frame())
  7. stopifnot(is.data.frame(.data))
  8. .var1 <- rlang::enexpr(.var1)
  9. .var2 <- rlang::enexpr(.var2)
  10. if (rlang::as_string(.var1) %in% names(.data)) {
  11. return(rlang::parse_expr(rlang::as_string(.var1)))
  12. } else if (rlang::as_string(.var2) %in% names(.data)) {
  13. return(rlang::parse_expr(rlang::as_string(.var2)))
  14. } else {
  15. return(.fill)
  16. }
  17. }
  18. df <- data.frame(
  19. ID = c("ID01", "ID01", "ID02", "ID02"),
  20. v1 = c("a", "b", "c", NA),
  21. v2 = c("A", "B", "C", "C")
  22. )

以下是示例用法的翻译:

返回第一个存在的列

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v1))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A a
  4. #> 2 ID01 b B b
  5. #> 3 ID02 c C c
  6. #> 4 ID02 <NA> C <NA>

返回两列中的第一个存在的列

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v2, v1))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A A
  4. #> 2 ID01 b B B
  5. #> 3 ID02 c C C
  6. #> 4 ID02 <NA> C C

返回两列中的第二个存在的列

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v1_x, v2))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A A
  4. #> 2 ID01 b B B
  5. #> 3 ID02 c C C
  6. #> 4 ID02 <NA> C C

如果两列不存在,则返回 NA

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v1_X, v2_X))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A NA
  4. #> 2 ID01 b B NA
  5. #> 3 ID02 c C NA
  6. #> 4 ID02 <NA> C NA

在分组的数据框上正常工作

  1. df %>%
  2. dplyr::group_by(ID) %>%
  3. dplyr::mutate(NEW = !!return_exist_var(v1))
  4. #> # 一个 tibble:4 × 4
  5. #> # 组: ID [2]
  6. #> ID v1 v2 NEW
  7. #> <chr> <chr> <chr> <chr>
  8. #> 1 ID01 a A a
  9. #> 2 ID01 b B b
  10. #> 3 ID02 c C c
  11. #> 4 ID02 <NA> C <NA>
英文:

The following function return first existing column in data frame, or NA if no existing columns

  1. library(dplyr, warn.conflicts = FALSE)
  2. #> Warning: package 'dplyr' was built under R version 4.2.3
  3. # `dplyr::coalesce` return fist non-missing, but these columns must exist
  4. return_exist_var <- function(.var1, .var2, .fill = NA, .data) {
  5. # get the . from magrittr::%>%
  6. .data <- get(".", parent.frame())
  7. stopifnot(is.data.frame(.data))
  8. .var1 <- rlang::enexpr(.var1)
  9. .var2 <- rlang::enexpr(.var2)
  10. if (rlang::as_string(.var1) %in% names(.data)) {
  11. return(rlang::parse_expr(rlang::as_string(.var1)))
  12. } else if (rlang::as_string(.var2) %in% names(.data)) {
  13. return(rlang::parse_expr(rlang::as_string(.var2)))
  14. } else {
  15. return(.fill)
  16. }
  17. }
  18. df <- data.frame(
  19. ID = c("ID01", "ID01", "ID02", "ID02"),
  20. v1 = c("a", "b", "c", NA),
  21. v2 = c("A", "B", "C", "C")
  22. )

return first existing column

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v1))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A a
  4. #> 2 ID01 b B b
  5. #> 3 ID02 c C c
  6. #> 4 ID02 <NA> C <NA>

return first existing column in two column

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v2, v1))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A A
  4. #> 2 ID01 b B B
  5. #> 3 ID02 c C C
  6. #> 4 ID02 <NA> C C

return second existing column in two column

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v1_x, v2))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A A
  4. #> 2 ID01 b B B
  5. #> 3 ID02 c C C
  6. #> 4 ID02 <NA> C C

return NA if two column not eixst

  1. df %>% dplyr::mutate(NEW = !!return_exist_var(v1_X, v2_X))
  2. #> ID v1 v2 NEW
  3. #> 1 ID01 a A NA
  4. #> 2 ID01 b B NA
  5. #> 3 ID02 c C NA
  6. #> 4 ID02 <NA> C NA

work well on grouped data frame

  1. df %>%
  2. dplyr::group_by(ID) %>%
  3. dplyr::mutate(NEW = !!return_exist_var(v1))
  4. #> # A tibble: 4 × 4
  5. #> # Groups: ID [2]
  6. #> ID v1 v2 NEW
  7. #> <chr> <chr> <chr> <chr>
  8. #> 1 ID01 a A a
  9. #> 2 ID01 b B b
  10. #> 3 ID02 c C c
  11. #> 4 ID02 <NA> C <NA>

Problem

How to update the function, then call function like below without !!, or define a new same function

df %>% dplyr::mutate(NEW = return_exist_var(v1))

答案1

得分: 1

这是您的函数的简化版本,它依赖于使用 any_of() 来处理缺失的变量。由于 any_of() 需要字符向量作为参数,因此在使用之前需要解析参数。

  1. library(dplyr)
  2. return_exist_var <- function(...) {
  3. var_list <- match.call(expand.dots = FALSE)$...
  4. c(pick(any_of(sapply(var_list, deparse))), NA)[[1]]
  5. }
  6. df %>%
  7. dplyr::mutate(NEW = return_exist_var(v1))
  8. ID v1 v2 NEW
  9. 1 ID01 a A a
  10. 2 ID01 b B b
  11. 3 ID02 c C c
  12. 4 ID02 <NA> C <NA>
  13. df %>%
  14. dplyr::mutate(NEW = return_exist_var(v2, v1))
  15. ID v1 v2 NEW
  16. 1 ID01 a A A
  17. 2 ID01 b B B
  18. 3 ID02 c C C
  19. 4 ID02 <NA> C C
  20. df %>%
  21. dplyr::mutate(NEW = return_exist_var(v1_x, v2))
  22. ID v1 v2 NEW
  23. 1 ID01 a A A
  24. 2 ID01 b B B
  25. 3 ID02 c C C
  26. 4 ID02 <NA> C C
  27. df %>%
  28. dplyr::mutate(NEW = return_exist_var(v1_X, v2_X))
  29. ID v1 v2 NEW
  30. 1 ID01 a A <NA>
  31. 2 ID01 b B <NA>
  32. 3 ID02 c C <NA>
  33. 4 ID02 <NA> C <NA>
  34. # 如果数据已分组,也适用
  35. df %>%
  36. mutate(NEW = return_exist_var(v1), .by = ID)
  37. ID v1 v2 NEW
  38. 1 ID01 a A a
  39. 2 ID01 b B b
  40. 3 ID02 c C c
  41. 4 ID02 <NA> C <NA>
英文:

Here is a simplified version of your function that relies on using any_of() to handle missing vars. As any_of() requires a character vector, the arguments need to be deparsed before use.

  1. library(dplyr)
  2. return_exist_var &lt;- function(...) {
  3. var_list &lt;- match.call(expand.dots = FALSE)$...
  4. c(pick(any_of(sapply(var_list, deparse))), NA)[[1]]
  5. }
  6. df %&gt;%
  7. dplyr::mutate(NEW = return_exist_var(v1))
  8. ID v1 v2 NEW
  9. 1 ID01 a A a
  10. 2 ID01 b B b
  11. 3 ID02 c C c
  12. 4 ID02 &lt;NA&gt; C &lt;NA&gt;
  13. df %&gt;%
  14. dplyr::mutate(NEW = return_exist_var(v2, v1))
  15. ID v1 v2 NEW
  16. 1 ID01 a A A
  17. 2 ID01 b B B
  18. 3 ID02 c C C
  19. 4 ID02 &lt;NA&gt; C C
  20. df %&gt;%
  21. dplyr::mutate(NEW = return_exist_var(v1_x, v2))
  22. ID v1 v2 NEW
  23. 1 ID01 a A A
  24. 2 ID01 b B B
  25. 3 ID02 c C C
  26. 4 ID02 &lt;NA&gt; C C
  27. df %&gt;%
  28. dplyr::mutate(NEW = return_exist_var(v1_X, v2_X))
  29. ID v1 v2 NEW
  30. 1 ID01 a A NA
  31. 2 ID01 b B NA
  32. 3 ID02 c C NA
  33. 4 ID02 &lt;NA&gt; C NA
  34. # Works if data is grouped
  35. df %&gt;%
  36. mutate(NEW = return_exist_var(v1), .by = ID)
  37. ID v1 v2 NEW
  38. 1 ID01 a A a
  39. 2 ID01 b B b
  40. 3 ID02 c C c
  41. 4 ID02 &lt;NA&gt; C &lt;NA&gt;

huangapple
  • 本文由 发表于 2023年6月29日 10:23:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577706.html
匿名

发表评论

匿名网友

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

确定