[英]In R, use dplyr::across and compute difference between 2 columns, for multiple column prefixes
zed <- data.frame(
aAgg = c(5, 10, 15, 20),
bAgg = c(8, 16, 24, 32),
aPg = c(6, 9, 11, 24),
bPg = c(7, 15, 22, 26)
)
diff_func <- function(col) {
return(`{col}Agg` - `{colPg}`)
}
zed %>%
dplyr::mutate(dplyr::across(.cols = c('a', 'b'), .fns = diff_func, .names = "{col}Diff"))
# we want the output that this outputs, without having to have a mutate for each field.
zed <- zed %>%
dplyr::mutate(aDiff = aAgg - aPg) %>%
dplyr::mutate(bDiff = bAgg - bPg)
我們正在嘗試across
function 中使用 dplyr 來創建多個列。 對於每個列前綴(在這種情況下a
和b
),我們想計算prefixAgg
- prefixPg
之間的差異,並將新列命名為prefixDiff
。 上面示例中的最后 3 行代碼生成所需的 output。 我們的diff_func
當前不正確,拋出錯誤。
是否有一個我們可以傳遞的across
將生成這個 output?
我們可能需要遍歷“Agg”列或“Pg”列,並在從列名( cur_column()
)中替換 substring 並修改.names
后get
相應的列
library(dplyr)
library(stringr)
zed %>%
mutate(across(ends_with("Agg"), ~ .x -
get(str_replace(cur_column(), "Agg", "Pg")),
.names = "{str_replace(.col, 'Agg', 'Diff')}"))
-輸出
aAgg bAgg aPg bPg aDiff bDiff
1 5 8 6 7 -1 1
2 10 16 9 15 1 1
3 15 24 11 22 4 2
4 20 32 24 26 -4 6
或者使用兩個 cross ,得到across
- 結果列將是 data.frame/tibble,然后unpack
data.frame 列
library(tidyr)
zed %>%
mutate(Diff = across(ends_with("Agg")) - across(ends_with("Pg"))) %>%
unpack(where(is.data.frame), names_sep = "")
# A tibble: 4 × 6
aAgg bAgg aPg bPg DiffaAgg DiffbAgg
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 5 8 6 7 -1 1
2 10 16 9 15 1 1
3 15 24 11 22 4 2
4 20 32 24 26 -4 6
注意:如果需要,可以重命名列
zed %>%
mutate(across(ends_with("Agg"),
.names = "{str_remove(.col, 'Agg')}Diff") -
across(ends_with("Pg")))
aAgg bAgg aPg bPg aDiff bDiff
1 5 8 6 7 -1 1
2 10 16 9 15 1 1
3 15 24 11 22 4 2
4 20 32 24 26 -4 6
或者也可以將dplyover
與across2
一起使用
library(dplyover)
zed %>%
mutate(across2(ends_with("Agg"), ends_with("Pg"), `-`,
.names_fn = ~ str_replace(.x, "Agg_.*", "Diff")))
aAgg bAgg aPg bPg aDiff bDiff
1 5 8 6 7 -1 1
2 10 16 9 15 1 1
3 15 24 11 22 4 2
4 20 32 24 26 -4 6
為什么不只是:
zed <- zed %>%
mutate(aDiff = aAgg - aPg,
bDiff = bAgg - bPg)
據我所知,你不能傳遞不同的前綴,但如果你願意,你可以重命名。 我不知道您為什么要為此使用cross,您能澄清一下嗎?
split.default
和dplyr
解決方案(可能接近您可以獲得的最快解決方案;請參見此處):
zed <- data.frame(
aAgg = c(5, 10, 15, 20),
bAgg = c(8, 16, 24, 32),
aPg = c(6, 9, 11, 24),
bPg = c(7, 15, 22, 26)
)
library(dplyr, warn.conflicts = F)
zed %>%
split.default(
sub('^(.{1}).*', '\\1', names(zed))
) %>%
lapply(
function(.x) .x[[1]] - .x[[2]]
) %>%
setNames(., paste0(names(.), 'Diff')) %>%
mutate(zed, !!!.)
#> aAgg bAgg aPg bPg aDiff bDiff
#> 1 5 8 6 7 -1 1
#> 2 10 16 9 15 1 1
#> 3 15 24 11 22 4 2
#> 4 20 32 24 26 -4 6
由reprex package (v2.0.1) 於 2022 年 8 月 9 日創建
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.