使用dplyr在行中应用函数到选定列

3
新的 dplyr 1.0.0 版本使得 处理行更加容易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 功能,在不转置数据框的情况下实现。

我找到的最近的解决方案使用了 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 

就像列一样吗?

虽然 dplyr 已经让行操作变得容易,但我认为它仍不是处理逐行操作的最佳工具。 - Ronak Shah
@Ronak Shah,感谢您的评论:我同意,处理行变得更容易了,但与列相比,它还没有完全对称。 - Waldi
1个回答

1
我们可以直接使用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

如果我们使用原帖作者的方法
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

或者对于选择的列

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

感谢@akrun的回答。如果我使用select(is.numeric)而不是everything(),它是否也适用于任何dplyr动词 - Waldi
感谢@akrun,transmute正是我正在寻找的! - Waldi
@Waldi 谢谢。我在考虑你之前关于select的评论。你能否更新一下你的帖子? - akrun
@Waldi 我更新了帖子,但对我来说似乎仍然不够直接。 - akrun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接