[英]How to transform this base R code to dplyr using across and .names arguement
我有這個 dataframe:
df <- structure(list(A = c(2L, 3L, 4L, 5L, 5L), B = c(3L, 1L, 2L, 5L,
5L), C = c(4L, 5L, 2L, 1L, 1L), D = c(3L, 1L, 5L, 1L, 2L)), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -5L))
A B C D
<int> <int> <int> <int>
1 2 3 4 3
2 3 1 5 1
3 4 2 2 5
4 5 5 1 1
5 5 5 1 2
我想用它的下一列減去每一列!
我可以使用此處的基本 R 代碼執行此操作 從R 中的許多列中減去 dataframe 中的一列:
df[-1] - df[-ncol(df)]
B C D
1 1 1 -1
2 -2 4 -4
3 -2 0 3
4 0 -4 0
5 0 -4 1
由於.names
參數,我想使用across
並將此代碼轉換為dplyr
預計 Output:
A B C D B-A C-B D-C
1 2 3 4 3 1 1 -1
2 3 1 5 1 -2 4 -4
3 4 2 2 5 -2 0 3
4 5 5 1 1 0 -4 0
5 5 5 1 2 0 -4 1
我的第一次嘗試:
library(dplyr)
df %>%
mutate(across(everything(), ~df[-1] - df[-ncol(df)], .names = "{.col}-{.col}")) %>%
select(contains("-"))
`A-A`$B $C $D `B-B`$B $C $D `C-C`$B $C $D `D-D`$B $C $D
<int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 1 1 -1 1 1 -1 1 1 -1 1 1 -1
2 -2 4 -4 -2 4 -4 -2 4 -4 -2 4 -4
3 -2 0 3 -2 0 3 -2 0 3 -2 0 3
4 0 -4 0 0 -4 0 0 -4 0 0 -4 0
5 0 -4 1 0 -4 1 0 -4 1 0 -4 1
我的第二次嘗試:
df %>%
mutate(across(everything(), ~.[-1] - .[-ncol(.)], .names = "{.col}-{.col}"))
Error in `mutate()`:
! Problem while computing
`..1 = across(everything(), ~.[-1]
- .[-ncol(.)], .names =
"{.col}-{.col}")`.
Caused by error in `across()`:
! Problem while computing
column `A-A`.
Caused by error in `-ncol(A)`:
! invalid argument to unary operator
Run `rlang::last_error()` to see where the error occurred.
有更簡單的方法,但如果我們想across
library(dplyr)
df %>%
mutate(across(-1, ~ {
prevnm <- names(cur_data())[match(cur_column(), names(cur_data()))-1]
.x - df[[prevnm]]},
.names = "{.col}-{names(.)[match(.col, names(.))-1]}"))
-輸出
# A tibble: 5 × 7
A B C D `B-A` `C-B` `D-C`
<int> <int> <int> <int> <int> <int> <int>
1 2 3 4 3 1 1 -1
2 3 1 5 1 -2 4 -4
3 4 2 2 5 -2 0 3
4 5 5 1 1 0 -4 0
5 5 5 1 2 0 -4 1
或者使用兩個across
df %>%
mutate(across(-1, .names = "{.col}-{names(.)[match(.col,
names(.))-1]}") - across(-last_col()))
# A tibble: 5 × 7
A B C D `B-A` `C-B` `D-C`
<int> <int> <int> <int> <int> <int> <int>
1 2 3 4 3 1 1 -1
2 3 1 5 1 -2 4 -4
3 4 2 2 5 -2 0 3
4 5 5 1 1 0 -4 0
5 5 5 1 2 0 -4 1
此外,還有一個更緊湊的選項,來自across2
的dplyover
library(dplyover) #https://github.com/TimTeaFan/dplyover
df %>%
mutate(across2(-1, -last_col(), ~.x -.y, .names = "{xcol}-{ycol}"))
# A tibble: 5 × 7
A B C D `B-A` `C-B` `D-C`
<int> <int> <int> <int> <int> <int> <int>
1 2 3 4 3 1 1 -1
2 3 1 5 1 -2 4 -4
3 4 2 2 5 -2 0 3
4 5 5 1 1 0 -4 0
5 5 5 1 2 0 -4 1
如果.names
可以使用默認的下划線作為分隔符,那就更簡單了
df %>%
mutate(across2(-1, -last_col(), `-`))
# A tibble: 5 × 7
A B C D B_A C_B D_C
<int> <int> <int> <int> <int> <int> <int>
1 2 3 4 3 1 1 -1
2 3 1 5 1 -2 4 -4
3 4 2 2 5 -2 0 3
4 5 5 1 1 0 -4 0
5 5 5 1 2 0 -4 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.