Я пытаюсь сгенерировать несколько новых столбцов / переменных в фрейме данных R с новыми динамическими именами, взятыми из вектора. Новые переменные вычисляются из групп / уровней одного столбца. Кадр данных содержит измерения ( количество ) различных химических элементов ( элемент ) по глубине ( z ). Новые переменные вычисляются путём подсчета количества каждого элемента на определенной глубине на соответствующее количество элементов-посредников ( прокси ) на той же глубине.
Уже есть решение с использованием mutateэто работает, если я только хочу создать один новый столбец / назвать столбцы явно (см. код ниже). Я ищу обобщенное решение для использования в блестящем веб-приложении, где прокси является не строкой, а вектором строк и динамически изменяется в соответствии с пользовательским вводом.
# Working code for just one new column at a time (here Ti_ratio)
proxies <- "Ti"
df <- tibble(z = rep(1:10, 4), element = rep(c("Ag", "Fe", "Ca", "Ti"), each = 10), counts = rnorm(40))
df_Ti <- df %>%
group_by(z) %>%
mutate(Ti_ratio = counts/counts[element %in% proxies])
# Not working code for multiple columns at a time
proxies <- c("Ca", "Fe", "Ti")
varname <- paste(proxies, "ratio", sep = "_")
df_ratios <- df %>%
group_by(z) %>%
map(~ mutate(!!varname = .x$counts/.x$counts[element %in% proxies]))
Вывод рабочего кода:
> head(df_Ti)
# A tibble: 6 x 4
# Groups: z [6]
z element counts Ti_ratio
<int> <chr> <dbl> <dbl>
1 1 Ag 2.41 4.10
2 2 Ag -1.06 -0.970
3 3 Ag -0.312 -0.458
4 4 Ag -0.186 0.570
5 5 Ag 1.12 -1.38
6 6 Ag -1.68 -2.84
Ожидаемый вывод не рабочего кода:
> head(df_ratios)
# A tibble: 6 x 6
# Groups: z [6]
z element counts Ca_ratio Fe_ratio Ti_ratio
<int> <chr> <dbl> <dbl> <dbl> <dbl>
1 1 Ag 2.41 4.78 -10.1 4.10
2 2 Ag -1.06 3.19 0.506 -0.970
3 3 Ag -0.312 -0.479 -0.621 -0.458
4 4 Ag -0.186 -0.296 -0.145 0.570
5 5 Ag 1.12 0.353 3.19 -1.38
6 6 Ag -1.68 -2.81 -0.927 -2.84
Редактировать: Я нашел общее решение длямоя проблема с base R
с использованием двух вложенных циклов for, похожая на ответ, опубликованный @fra (разница в том, что здесь я зацикливаюсь как по глубине, так и по прокси):
library(tidyverse)
df <- tibble(z = rep(1:3, 4), element = rep(c("Ag", "Ca", "Fe", "Ti"), each = 3), counts = runif(12)) %>% arrange(z, element)
proxies <- c("Ca", "Fe", "Ti")
for (f in seq_along(proxies)) {
proxy <- proxies[f]
tmp2 <- NULL
for (i in unique(df$z)) {
tmp <- df[df$z == i,]
tmp <- as.data.frame(tmp$counts/tmp$counts[tmp$element %in% proxy])
names(tmp) <- paste(proxy, "ratio", sep = "_")
tmp2 <- rbind(tmp2, tmp)
}
df[, 3 + f] <- tmp2
}
и правильныйoutput:
> head(df)
# A tibble: 6 x 6
z element counts Ca_ratio Fe_ratio Ti_ratio
<int> <chr> <dbl> <dbl> <dbl> <dbl>
1 1 Ag 0.690 0.864 9.21 1.13
2 1 Ca 0.798 1 10.7 1.30
3 1 Fe 0.0749 0.0938 1 0.122
4 1 Ti 0.612 0.767 8.17 1
5 2 Ag 0.687 0.807 3.76 0.730
6 2 Ca 0.851 1 4.66 0.904
Я сделал так, чтобы в фрейме данных было меньше данных, чтобы было ясно, почему это решение верное (Соотношение элементов с самими собой = 1). Я все еще заинтересован в более элегантном решении, которое я мог бы использовать с трубами.