使用 purrr:pmap_dbl 计算多列每行的平均值(数量事先未知)

Gio*_*oni 5 r purrr tidyverse

我希望能够:

(1) 编写一个简单的函数来计算字符串向量的平均字符串长度

(2) 在 data.frame 中选择一堆多个字符串列来计算每行的字符串长度平均值

(3) 使用我的函数purrr::pmap_dbl

我能够通过以下方式执行(1)、(2)和(3):

library(tidyverse)

df <- tibble(q0 = c("a", "b", "c"),
             q1 = c("aa", "bb", "cc"),
             q2 = c("aaa", "b", NA),
             some_other_var = 1:3)

avg_str_len <- function(...) mean(str_length(c(...)), na.rm = TRUE)

df %>%
  mutate(avg_len = pmap_dbl(select(., q0:q2), avg_str_len))

## A tibble: 3 x 5
#  q0    q1    q2    some_other_var avg_len
#  <chr> <chr> <chr>          <int>   <dbl>
#1 a     aa    aaa                1    2   
#2 b     bb    b                  2    1.33
#3 c     cc    NA                 3    1.5

# or if I don't know how many q columns:
df %>%
  mutate(avg_len = pmap_dbl(select(., starts_with("q")), avg_str_len))
Run Code Online (Sandbox Code Playgroud)

但我分别特别担心(1)和(2):

  1. 我真的需要这么复杂的功能吗?难道就没有更简单的方法吗?

  2. 我真的需要select选择多个列吗?是不是有一些类似或之类tidyselect的魔法可以发挥作用?(他们不……)vars(matches("q"))q0:q3

df %>%
  mutate(avg_len = pmap_dbl(q0:q2, avg_str_len))

#Error in q0:q2 : NA/NaN argument
#In addition: Warning messages:
#1: In q0:q2 : numerical expression has 3 elements: only the first used
#2: In q0:q2 : numerical expression has 3 elements: only the first used
#3: In is.data.frame(.l) : NAs introduced by coercion
#4: In is.data.frame(.l) : NAs introduced by coercion

df %>%
  mutate(avg_len = pmap_dbl(vars(matches("q")), avg_str_len))

#Error: Element 1 of `.l` must be a vector, not a `quosure/formula` object
#Call `rlang::last_error()` to see a backtrace.
Run Code Online (Sandbox Code Playgroud)

请注意,有多个q列,因此使用它们选择它们list(q0, q1, q2)太长,或者假设我事先不知道q我有多少列

tmf*_*mnk 2

一种仅涉及的选项dplyr可能是:

df %>%
 mutate(avg_len = rowMeans(select_if(., is_character) %>%
                         mutate_all(nchar), na.rm = TRUE))

  q0    q1    q2    some_other_var avg_len
  <chr> <chr> <chr>          <int>   <dbl>
1 a     aa    aaa                1    2   
2 b     bb    b                  2    1.33
3 c     cc    <NA>               3    1.5 
Run Code Online (Sandbox Code Playgroud)

或者,如果您只想要以 开头的列q

df %>%
 mutate(avg_len = rowMeans(select(., starts_with("q")) %>%
                            mutate_all(nchar), na.rm = TRUE))
Run Code Online (Sandbox Code Playgroud)