【发布时间】:2021-11-12 08:14:36
【问题描述】:
我有一个数据集,其中包含多个遵循名称模式的列,我需要计算新列,它是其他两列的乘积。我正在寻找一个 tidyverse 选项,但我想避免做一个 pivot_longer,因为数据集有 >百万行。
示例数据集
library(dplyr)
df <- tibble(
jan_mean = runif(10),
feb_mean = runif(10),
mar_mean = runif(10),
jan_sd = runif(10),
feb_sd = runif(10),
mar_sd = runif(10),
)
我可以像这样手动完成:
df2 <- df %>%
mutate(jan_cv= jan_mean/jan_sd,
feb_cv= feb_mean/feb_sd,
mar_cv= mar_mean/mar_sd
)
这是一个简单的例子,但我对月值有类似的操作。
编辑 1
我需要为大型数据集执行此操作,我担心pivot_longer 会非常消耗,所以我对这三种方法进行了快速比较。
Method 1 是手动方式,Method 2 是@Tarjae 建议的短版本,Method 3 是使用更长的pivot 方式:
tic("Method 1: manual option")
df2 <- df %>%
mutate(jan_cv= jan_mean/jan_sd,
feb_cv= feb_mean/feb_sd,
mar_cv= mar_mean/mar_sd
)
toc()
tic("Method 2: Short option")
df2 <- df %>%
mutate(across(ends_with('_mean'), ~ . /
get(str_replace(cur_column(), "mean$", "sd")), .names = "{.col}_cv")) %>%
rename_at(vars(ends_with('cv')), ~ str_remove(., "\\_mean"))
toc()
tic("Method 3: pivot wider option")
df2 <- df %>%
mutate(id = row_number()) %>%
pivot_longer(-id, names_to = c("month", ".value"), names_sep = "_") %>%
mutate(cv = mean / sd) %>%
pivot_wider(names_from = "month", values_from = c(mean, sd, cv), names_glue = "{month}_{.value}") %>%
select(-id)
toc()
结果是:
Method 1: manual option: 0.05 sec elapsed
Method 2: Short option: 0.01 sec elapsed
Method 3: pivot wider option: 0.19 sec elapsed
所以方法 2 比手动处理每一列还要快
【问题讨论】:
-
我认为您希望在最后一行的输出应该是:
mar_cv = mar_mean/mar_sd而不是mar_cv= jan_mean/mar_sd?