简体   繁体   English

使用 lambda 函数应用 dplyr::starts_with()

[英]Apply dplyr::starts_with() with lambda function

I have below implementation我有以下实施

library(dplyr)
library(tidyr)
dat = data.frame('A' = 1:3, 'C_1' = 1:3, 'C_2' = 1:3, 'M' = 1:3)

Below works以下作品

dat %>% rowwise %>% mutate(Anew = list({function(x) c(x[1]^2, x[2] + 5, x[3] + 1)}(c(M, C_1, C_2)))) %>% ungroup %>% unnest_wider(Anew, names_sep = "")

However below does not work when I try find the column names using dplyr::starts_with()但是,当我尝试使用dplyr::starts_with()查找列名时,下面不起作用

dat %>% rowwise %>% mutate(Anew = list({function(x) c(x[1]^2, x[2] + 5, x[3] + 1)}(c(M, starts_with('C_'))))) %>% ungroup %>% unnest_wider(Anew, names_sep = "")

Any pointer on how to correctly apply starts_with() in this context will be very helpful.关于如何在此上下文中正确应用starts_with()的任何指示都将非常有帮助。

PS: This is continuation from my earlier post Apply custom function that returns multiple values after dplyr::rowwise() PS:这是我之前发布的Apply custom function that returns multiple values after dplyr::rowwise()的延续

starts_with must be used within a selecting function so we can write this. starts_with必须在选择函数中使用,所以我们可以这样写。 across is also a selecting function so we could alternately use across(M | starts_with('C_')) in place of select(...) . across也是一个选择函数,因此我们可以交替使用across(M | starts_with('C_'))代替select(...) c_across is also a selecting function but it does not preserve names. c_across也是一个选择函数,但它不保留名称。

dat %>%
  rowwise %>%
  mutate(Anew = list({function(x) c(x[1]^2, x[2] + 5, x[3] + 1)}
    (select(cur_data(), M, starts_with('C_'))))) %>%
  ungroup %>%
  unnest_wider(Anew, names_sep = "")
## # A tibble: 3 × 7
##       A   C_1   C_2     M AnewM AnewC_1 AnewC_2
##   <int> <int> <int> <int> <dbl>   <dbl>   <dbl>
## 1     1     1     1     1     1       6       2
## 2     2     2     2     2     4       7       3
## 3     3     3     3     3     9       8       4

Here group_modify would also work and allow the use of formula notation to specify an anonymous function.这里group_modify也可以工作,并允许使用公式符号来指定匿名函数。 The indexes in the anonymous function have been reordered to correspond to the order in the input.匿名函数中的索引已重新排序以对应于输入中的顺序。

dat %>%
  group_by(A) %>%
  group_modify(~ cbind(.x, Anew = c(.x[3]^2, .x[1] + 5, .x[2] + 1))) %>%
  ungroup
## # A tibble: 3 × 7
##       A   C_1   C_2     M Anew.M Anew.C_1 Anew.C_2
##   <int> <int> <int> <int>  <dbl>    <dbl>    <dbl>
## 1     1     1     1     1      1        6        2
## 2     2     2     2     2      4        7        3
## 3     3     3     3     3      9        8        4

If we wrap the starts_with in c_across and assuming there is a third column that starts with C_ , then the lambda function on the fly would work如果我们将c_across包装在starts_with中并假设有第三列以C_开头,那么运行中的 lambda 函数将起作用

library(dplyr)
library(tidyr)
dat %>%
  rowwise %>%
   mutate(Anew = list((function(x) c(x[1]^2, x[2] + 5, x[3] + 
      1))(c_across(starts_with("C_"))))) %>%
  unnest_wider(Anew, names_sep = "")

-output -输出

# A tibble: 3 × 8
      A   C_1   C_2   C_3     M Anew1 Anew2 Anew3
  <int> <int> <int> <int> <int> <dbl> <dbl> <dbl>
1     1     1     1     1     1     1     6     2
2     2     2     2     2     2     4     7     3
3     3     3     3     3     3     9     8     4

Or instead of doing rowwise , we may create a named list of functions and apply column wise with across (would be more efficient)或者我们可以创建一个命名的函数rowwise ,而不是按行进行,并应用across list (会更有效率)

fns <- list(C_1 = function(x) x^2, C_2 = function(x) x + 5, 
      C_3 = function(x) x + 1)
dat %>%
   mutate(across(starts_with("C_"), 
    ~ fns[[cur_column()]](.x), .names = "Anew{seq_along(.fn)}"))

-output -输出

   A C_1 C_2 C_3 M Anew1 Anew2 Anew3
1 1   1   1   1 1     1     6     2
2 2   2   2   2 2     4     7     3
3 3   3   3   3 3     9     8     4

data数据

dat <- data.frame('A' = 1:3, 'C_1' = 1:3, 'C_2' = 1:3, C_3 = 1:3, 'M' = 1:3)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM