【问题标题】:Apply Multiple Columns to Custom function Using dplyr::mutate(across())使用 dplyr::mutate(across()) 将多列应用于自定义函数
【发布时间】:2020-09-03 20:56:03
【问题描述】:

df

a = c("aa", "bb", "cc", "bb", "bb", "cc","bb", "bb", "cc", "cc", "bb", "cc", "bb", "bb", "cc","bb", "bb", "cc", "cc", "bb","bb") 
b = c("aa", "bb", "cc", "bb", "bb", "cc","bb", "bb", "cc", "cc", "bb", "cc", "bb", "bb", "cc","bb", "bb", "cc", "cc", "bb","bb") 
c = c("aa", "aa", "aa", "bb", "bb", "cc","bb", "bb", "cc", "cc", "bb", "cc", "bb", "bb", "cc","bb", "bb", "cc", "cc", "bb","bb") 
d = c(1, 1, 2, 2, 3, 3, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 1, 1, 1, 1, 1)
df = data.frame(a,b,c,d)

列名称:

cols <- c("a","b","c")

功能:

rare_label <- function(x){
  freq = prop.table(table(unlist(x)))
  make_rare = names(freq)[freq < 0.20]
  lapply(x,
         function(x) {
           replace(x, x %in% make_rare, "Rare")
         })}

希望用dplyr::mutate(across()) 评估a、b、c 中组合所有值的比例,然后将比例低于20% 的任何类别更改为“稀有”。

输出:

     a    b    c
    Rare Rare Rare
    bb   bb   Rare
    cc   cc   Rare
    bb   bb   bb
    bb   bb   bb
    cc   cc   cc
    bb   bb   bb
    .    .    .
    .    .    .
    .    .    .
    

使用下面的代码会引发错误,我不确定为什么。

df %<>%
  mutate(across(where(cols), ~rare_label(.)

错误:出现意外符号:“ mutate(across(where(cols), ~rare_label(.) 查看"

【问题讨论】:

  • 您的第一行代码不起作用,其中一列较短
  • 已修复,抱歉

标签: r


【解决方案1】:

一个选项可能是:

df %>%
 mutate(across(all_of(cols), 
               ~ replace(., . %in% names(which(prop.table(table(.)) < 0.20)), "rare")))

      a    b    c d
1  rare rare rare 1
2    bb   bb rare 1
3    cc   cc rare 2
4    bb   bb   bb 2
5    bb   bb   bb 3
6    cc   cc   cc 3
7    bb   bb   bb 1
8    bb   bb   bb 1
9    cc   cc   cc 1
10   cc   cc   cc 1

如果要应用现有功能:

fun <- function(x) replace(x, x %in% names(which(prop.table(table(x)) < 0.20)), "rare")

df %>%
 mutate(across(all_of(cols), fun))

【讨论】:

  • 谢谢,但是如何通过函数进行计算?
  • 更新了帖子。
【解决方案2】:

您的代码运行良好,只需像这样更改管道和值:

#Code
df %>%
    mutate(across(c(a:c), ~rare_label(.))

输出:

      a    b    c d
1  Rare Rare Rare 1
2    bb   bb Rare 1
3    cc   cc Rare 2
4    bb   bb   bb 2
5    bb   bb   bb 3
6    cc   cc   cc 3
7    bb   bb   bb 1
8    bb   bb   bb 1
9    cc   cc   cc 1
10   cc   cc   cc 1
11   bb   bb   bb 1
12   cc   cc   cc 1
13   bb   bb   bb 2
14   bb   bb   bb 2
15   cc   cc   cc 3
16   bb   bb   bb 3
17   bb   bb   bb 1
18   cc   cc   cc 1
19   cc   cc   cc 1
20   bb   bb   bb 1
21   bb   bb   bb 1

【讨论】:

    【解决方案3】:

    您的功能是正确的,但您需要进行 2 处更改。

    1. 删除lapply 并保留最后一行:
    replace(x, x %in% make_rare, "Rare")
    
    1. across 中删除where,因为您是按他们的名字来调用列的。

    完成这些更改后,您的代码应该可以工作了。


    另一种选择是使用forcats 包,它具有执行此类操作的功能。

    library(dplyr)
    library(forcats)
    
    df %>% 
      mutate(across(all_of(cols),fct_lump_min, min = n() * .2, other_level = "rare"))
    
    #      a    b    c d
    #1  rare rare rare 1
    #2    bb   bb rare 1
    #3    cc   cc rare 2
    #4    bb   bb   bb 2
    #5    bb   bb   bb 3
    #6    cc   cc   cc 3
    #7    bb   bb   bb 1
    #8    bb   bb   bb 1
    #9    cc   cc   cc 1
    #10   cc   cc   cc 1
    #11   bb   bb   bb 1
    #12   cc   cc   cc 1
    #13   bb   bb   bb 2
    #...
    

    fct_lump_min 将所有发生率低于 20% (0.2 * n()) 的因素更改为“罕见”。这里我们为n 传递一个数字以降低水平,我找不到通过传递比例本身起作用的函数,fct_lump_prop 做了其他事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多