首页 > 解决方案 > 使用 dplyr 将函数应用于一行中的选定列

问题描述

dplyr版本 1.0.0 使使用 rows 变得更加容易

across允许在整个列上应用函数,用dplyr动词选择,例如sorteverything()

set.seed(1)
df <- as.data.frame(matrix(sample.int(5, 25, TRUE), 5, 5))
df
  V1 V2 V3 V4 V5
1  1  3  5  5  5
2  4  2  5  5  2
3  1  3  2  1  2
4  2  3  2  1  1
5  5  1  1  5  4

df %>% mutate(across(everything(),sort))
  V1 V2 V3 V4 V5
1  1  1  1  1  1
2  1  2  2  1  2
3  2  3  2  5  2
4  4  3  5  5  4
5  5  3  5  5  5

同样,我想在行中的选定列上应用一个函数,利用更新的rowwise dplyr功能,而不转置 dataframe

我找到的最接近的解决方案使用c_across

df %>% rowwise %>%
       mutate(sortlist = list(sort(c_across(everything())))) %>%
       unnest_wider(sortlist)

# A tibble: 5 x 10
     V1    V2    V3    V4    V5  ...1  ...2  ...3  ...4  ...5
  <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1     1     3     5     5     5     1     3     5     5     5
2     4     2     5     5     2     2     2     4     5     5
3     1     3     2     1     2     1     1     2     2     3
4     2     3     2     1     1     1     1     2     2     3
5     5     1     1     5     4     1     1     4     5     5

但是有没有dplyr办法直接到达:

  V1 V2 V3 V4 V5 
1  1  3  5  5  5 
2  2  2  4  5  5 
3  1  1  2  2  3 
4  1  1  2  2  3 
5  1  1  4  5  5 

就像列的情况一样?

标签: rdplyrrow

解决方案


我们可以pmap直接使用而不是两个步骤rowwise/c_across

library(dplyr)
library(purrr)
df %>% 
    pmap_dfr(~ set_names(sort(c(...)), names(df)))
# A tibble: 5 x 5
#     V1    V2    V3    V4    V5
#  <int> <int> <int> <int> <int>
#1     1     3     5     5     5
#2     2     2     4     5     5
#3     1     1     2     2     3
#4     1     1     2     2     3
#5     1     1     4     5     5

或者如果我们使用 OP 的方法

library(tidyr)
df %>%
   rowwise %>%
   transmute(sortlist = list(sort(c_across(everything())))) %>% 
   unnest_wider(c(sortlist)) %>%
   set_names(names(df))
# A tibble: 5 x 5
#     V1    V2    V3    V4    V5
#  <int> <int> <int> <int> <int>
#1     1     3     5     5     5
#2     2     2     4     5     5
#3     1     1     2     2     3
#4     1     1     2     2     3
#5     1     1     4     5     5

或者对于selected 列

df %>% 
  rowwise %>% 
  transmute(V1, V2, sortlist = list(sort(c_across(V3:V5)))) %>% 
  unnest_wider(c(sortlist)) %>%
  set_names(names(df))

推荐阅读