【问题标题】:Average over columns that start with a string using dplyr使用 dplyr 对以字符串开头的列进行平均
【发布时间】:2020-05-18 07:59:03
【问题描述】:

假设我想使用 dplyr 对所有以字符串开头的列进行平均。我使用平均的原因不是我对这个平均函数感兴趣,而是举一个简单的例子,因为事实上我更感兴趣的是使用更复杂的函数,它需要未知数量的列作为输入。我尝试使用:

iris %>%  mutate_at(vars(starts_with("Sepal")), funs(size=mean))

但最终在所有行中获得相同的数字。所以我尝试了:

iris %>% rowwise() %>% mutate_at(vars(starts_with("Sepal")), funs(size=mean))

但平均值适用于每个条目,因此不是我想要的平均值。例如对于 iris 数据集的第一行,我想得到 size=(5.1+3.5)/2。

我该怎么办?


更新:按照@Ronack 的回答,我在下面编写了这行代码。

codes <- c("J13","J14",paste0("J", c(seq(150,160))),"J170")

is_in_set <- function(x) {
  return(any(x %in% codes))
}

bd_test <- bd %>% 
  mutate(is_pneumonia = pmap_lgl(select(., starts_with('f.41270.0')), ~is_in_set(c(...))))

当我在函数上设置断点时,我的调试器会显示函数的输入:

Browse[2]> x
  f.41270.0.0   f.41270.0.1   f.41270.0.2   f.41270.0.3   f.41270.0.4   f.41270.0.5   f.41270.0.6   f.41270.0.7   f.41270.0.8   f.41270.0.9 
         1025           938           833           705           797           917          1307          2656          3206          3018 
 f.41270.0.10  f.41270.0.11  f.41270.0.12  f.41270.0.13  f.41270.0.14  f.41270.0.15  f.41270.0.16  f.41270.0.17  f.41270.0.18  f.41270.0.19 
         3701          4656          4659          4398          4294            NA            NA            NA            NA            NA 
 f.41270.0.20  f.41270.0.21  f.41270.0.22  f.41270.0.23  f.41270.0.24  f.41270.0.25  f.41270.0.26  f.41270.0.27  f.41270.0.28  f.41270.0.29 
           NA            NA            NA            NA            NA            NA            NA            NA            NA            NA 

应该是这样的

> bd %>% select(starts_with("f.41270.0"))%>% head(1)
  f.41270.0.0 f.41270.0.1 f.41270.0.2 f.41270.0.3 f.41270.0.4 f.41270.0.5 f.41270.0.6 f.41270.0.7 f.41270.0.8 f.41270.0.9 f.41270.0.10
1        D467        D619        D696         D70        E831         G10         I10        M478        N189         N19         R931
  f.41270.0.11 f.41270.0.12 f.41270.0.13 f.41270.0.14 f.41270.0.15 f.41270.0.16 f.41270.0.17 f.41270.0.18 f.41270.0.19 f.41270.0.20
1         Y848         Z513         Z538         Z539         <NA>         <NA>         <NA>         <NA>         <NA>         <NA>
  f.41270.0.21 f.41270.0.22 f.41270.0.23 f.41270.0.24 f.41270.0.25 f.41270.0.26 f.41270.0.27 f.41270.0.28 f.41270.0.29 f.41270.0.30
1         <NA>         <NA>         <NA>         <NA>         <NA>         <NA>         <NA>         <NA>         <NA>         <NA>

这些字符串被转换为一些任意数字,因为 ' 保持不变。如果您制作的数据集仅包含上述这些,您将获得相同的结果,因此这是一个可用于重现结果的数据集。

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    说实话,我不太明白你的目标是什么,但也许是这个?

       iris %>%
         mutate(size = rowMeans(select(., starts_with("Sepal")), na.rm = T)
    

    【讨论】:

    • 就像我说的,我对平均函数不感兴趣。我想应用更通用的功能。我只是以均值为例。
    【解决方案2】:

    你可以使用rowMeans

    iris$size <- rowMeans(iris[grep('^Sepal', names(iris))])
    

    如果函数比较复杂,我们不能直接使用像rowMeans这样的内置函数,我们可以使用pmap函数。

    library(dplyr)
    library(purrr)
    
    iris %>% mutate(size = pmap_dbl(select(., starts_with('Sepal')), ~mean(c(...))))
    

    【讨论】:

    • 就像我说的,我对平均函数不感兴趣。我想应用更通用的功能。我只是以均值为例。
    • 这里的 c(...) 是什么?那么我应该为任意函数使用~function_name(c(...)) 吗?
    • 是的,在第二个选项中将mean 替换为您的函数名称。
    • 我明白了。所以你说 pmap 是唯一可能没有更简单的解决方案的方法? (例如,仅使用 dplyr)
    • 我什么时候说过pmap是唯一的方法?简单是上下文和主观的。还有其他方法,例如使用rowwise 或将数据转换为长格式并应用该函数,但在不了解您的函数的更多细节的情况下,我很难提出其他替代方案。
    猜你喜欢
    • 2020-01-03
    • 2015-06-14
    • 2021-02-14
    • 1970-01-01
    • 2011-06-01
    • 2020-12-09
    • 2022-08-11
    • 2021-12-28
    • 2017-12-28
    相关资源
    最近更新 更多