Вот блок кода:
# scale the log of price per group (cut)
my_diamonds <- diamonds %>%
mutate(log_price = log(price)) %>%
group_by(cut) %>%
mutate(scaled_log_price = scale(log_price) %>% as.numeric) %>% # scale within each group as opposed to overall
nest() %>%
mutate(mean_log_price = map_dbl(data, ~ .x$log_price %>% mean)) %>%
mutate(sd_log_price = map_dbl(data, ~ .x$log_price %>% sd)) %>%
unnest %>%
select(cut, price, price_scaled:sd_log_price) %>%
ungroup
# for each cut, find the back transformed actual values (exp) of each unit of zscore between -3:3
for (i in -3:3) {
my_diamonds <- my_diamonds %>%
mutate(!! paste0('mean_', ifelse(i < 0 , 'less_', 'plus_'), abs(i), 'z') := map2(.x = mean_log_price, .y = sd_log_price, ~ (.x + (i * .y)) %>% exp) %>% unlist)
}
my_diamonds_split <- my_diamonds %>% group_split(cut)
split_names <- my_diamonds %>% mutate(cut = as.character(cut)) %>% group_keys(cut) %>% pull(cut)
names(my_diamonds_split) <- split_names
Теперь у меня есть переменная my_diamonds_split
, которая представляет собой список фреймов данных. Я хотел бы l oop поверх этих фреймов данных и каждый раз создавать новый ggplot.
Я могу использовать настраиваемую функцию этикетировщика с одним df, но я не знаю, как это сделать в al oop:
labeller <- function(x) {
paste0(x,"\n", scales::dollar(sd(ex_df$price) * x + mean(ex_df$price)))
}
ex_df <- my_diamonds_split$Ideal
ex_df %>%
ggplot(aes(x = scaled_log_price)) +
geom_density() +
scale_x_continuous(label = labeller, limits = c(-3, 3))
Это создает сюжет для «Идеальной» огранки бриллиантов. Я также получаю две точки данных на оси x, значения zscore на -2, 0 и 2, а также необработанные значения в долларах 3,8, 3,9 и 11,8 тыс.
введите описание изображения здесь
Когда я определяю функцию labeller, я должен указать df для масштабирования. Вместо этого попробовал разместить точку вместо my_df, надеясь, что на каждой итерации ggplot будет получать значение df на любой итерации:
labeller <- function(x) {
paste0(x,"\n", scales::dollar(sd(.$price) * x + mean(.$price)))
}
ex_df <- my_diamonds_split$Ideal
ex_df %>%
ggplot(aes(x = scaled_log_price)) +
geom_density() +
scale_x_continuous(label = labeller, limits = c(-3, 3))
Возвращает:
Ошибка в .data.frame (x): объект '.' не найдено
Затем я попытался написать функцию, которая принимает аргумент для масштабирования df с помощью:
labeller <- function(x, df) {
paste0(x,"\n", scales::dollar(sd(df$price) * x + mean(df$price)))
}
ex_df <- my_diamonds_split$Ideal
ex_df %>%
ggplot(aes(x = scaled_log_price)) +
geom_density() +
scale_x_continuous(label = labeller(df = ex_df), limits = c(-3, 3)) # because when it comes to running in real life, I will try something like labeller(df = my_diamonds_split[[i]])
Ошибка в paste0 (x, "\ n" , scale :: dollar (sd (df $ price) * x + mean (df $ price))): аргумент «x» отсутствует, значение по умолчанию не задано
Принимая во внимание, что масштабирование должно быть выполнено за итерацию, как я могу l oop over my_diamonds_split, и на каждой итерации генерировать ggplot, как указано выше?
labeller <- function(x) {
# how can I make df variable
paste0(x,"\n", scales::dollar(sd(df$price) * x + mean(df$price)))
}
for (i in split_names) {
my_diamonds_split[[i]] %>%
ggplot(aes(x = scaled_log_price)) +
geom_density() +
scale_x_continuous(label = labeller, # <--- here, labeller must be defined with df$price except that will difer on each iteration
limits = c(-3, 3))
}