【问题标题】:How to apply a custom function to each column of my dataframe如何将自定义函数应用于我的数据框的每一列
【发布时间】:2019-05-12 18:35:24
【问题描述】:

我正在尝试掌握 tidyverse 和 dplyr 方法,并希望将以下函数应用于数据框/数据表的每一列:

library(multimode)
funx <- function(x) {multimode::modetest(x, method = 'SI') }

然后尝试使用summary_all之类的东西开始,但我立即得到一个错误:

错误:列 mpg 的长度必须为 1(汇总值),而不是 8

library(dplyr)

mtcars %>%
     summarise_all(funx)

我希望最终得到一个新的数据框,它显示第 1 列中测试的 colnames,以及第 2 列中 modetest 的 p 值

从昨天(2019 年 5 月 23 日)更新软件包后,我的解决方案无法正常工作,以下代码现在打印 '.'点而不是列名 向github页面提交了一个帖子询问这个变化的原因:github

library(multimode)
funx <- function(x) {
    print(substitute(x))
    multires <- multimode::modetest(x, method = 'SI') 
    p <- multires$p.value}

mtcars %>% 
    select(1:2) %>%
    summarise_all(list(~ funx(.)))

更新具有讽刺意味的是,在得到关于 github 帖子的反馈后,使用新版本我们现在可以这样做:

   mtcars %>%
      select(1:2) %>%
        summarise_all(funx)

正如您所看到的,这与我在发布此问题时开始我的问题时使用的语法完全相同。所以,dplyr 团队做得很好,我会说语法更“自然”。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    summarise 只能输出单个元素。根据?summarise

    创建一个或多个标量变量来汇总现有 tbl 的变量。具有由 group_by() 创建的组的 Tbl 将在每个组的输出中产生一行。没有组的 Tbl 将产生一行。

    所以如果输出的长度大于 1,请将其包装在 listunnest

    library(dplyr)    
    out <- mtcars %>%
              summarise_all(list(~ list(funx(.))))
    

    如果我们提取单个值,例如p.value,则无需将其包装在list

    out1 <- mtcars %>% 
              select(1:2) %>%
              summarise_all(list(~ funx(.)$p.value))
    out1
    #    mpg   cyl
    #1 0.718 0.244
    

    可以用gather转换成两列数据集

    library(tidyr)
    gather(out1, colName, pvalue) %>%
          arrange(pvalue)
    

    通过检查modetest 在单个列上的输出

    funx(mtcars[[1]])
    
    #   Silverman (1981) critical bandwidth test
    
    #data:  x
    #Critical bandwidth = 2.5413, p-value = 0.716
    #alternative hypothesis: true number of modes is greater than 1
    

    不是单值输出,而是汇总模型输出。因此,最好存储在list 中,但是,我们可以提取特定组件(p-value)并将其输出到summarise

    【讨论】:

    • 酷,确实很好用。您是否也知道如何将结果转置为 2 列输出,并通过增加 p 值对其进行排序?
    • @Mark Just do %&gt;% gather %&gt;% arrange(value)
    • 好的,我添加了 %>% rename(key = Parameter, value = p-value) 来重新标记它们。感谢 akrun 的帮助!
    • @Mark 你可以创建一个tibble,用list包裹它,然后unnest
    • 啊,当然。我也可以简单地在 funx 中使用替代(y)来获取它。我一定是过度专注于其他事情而忘记了那个简单的解决方案
    猜你喜欢
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 2021-08-07
    • 1970-01-01
    • 2020-10-28
    • 2015-12-05
    • 1970-01-01
    相关资源
    最近更新 更多