Как процитировать вновь созданную переменную в функции вспомогательной функции?

Вопрос

Как правильно заключать в кавычки параметр в функции, которая будет использоваться для создания новой переменной, которая будет передана другой функции?

Фон

Конечная цель - создать метки в фрейме данных для карты дерева с двумя уровнями иерархии, и я пытаюсь создать функцию многократного использования. Вот более простой пример:

Пример

library(scales)
library(tidyverse)

# Create dataframe
region = rep(c("North", "South"), 3)
district <- sprintf("Dist-%d", 1:6)
sales <- seq(2000, 1500000000, length.out = 6)

df <- tibble(region, district, sales)
df
# A tibble: 6 × 3
  region district      sales
  <chr>  <chr>         <dbl>
1 North  Dist-1         2000
2 South  Dist-2    300001600
3 North  Dist-3    600001200
4 South  Dist-4    900000800
5 North  Dist-5   1200000400
6 South  Dist-6   1500000000

Я создал эту вспомогательную функцию для форматирования валюты. Он будет использоваться в основной функции, и моя проблема связана с передачей нового имени переменной из основной функции в этот помощник:

# First function for formatting currency
mydollars <- scales::label_dollar(prefix = "$",
                          largest_with_cents = 5000,
                          scale_cut = c(0, " K" = 1e3, " M" = 1e6, " B" = 1e9, " T" = 1e12)
)
# Example function output
mydollars(df$sales)
[1] "$2 K"   "$300 M" "$600 M" "$900 M" "$1.2 B" "$1.5 B"

Это основная функция, которая использует вышеупомянутый помощник. Я передаю фрейм данных в функцию, создавая метку 2-го уровня «.index», затем я группирую и агрегирую числовой столбец, к которому я добавляю суффикс «2», поэтому я знаю, что это второе число, и возникает моя проблема изнутри paste() с mydollars("{{agg_number}}2"). Если я заменю этот код на "Test String", функция заработает.

treemap_index1 <- function(df, category1, category2, agg_number){
  
  df_out <- df %>% 
    mutate("{{category2}}.index" := paste({{category2}}, mydollars({{agg_number}}), sep = "\n")) %>% 
    group_by({{category1}}) %>%
    mutate("{{agg_number}}2" := sum({{agg_number}}),
           "{{category1}}.index" := paste({{category1}}, 
                                          mydollars("{{agg_number}}2"), # Code breaks on this line
                                          sep = "\n")) %>%
    print()
  
  return(df_out)
  
}

treemap_index1(df, region, district, sales)

 rlang::last_error()
<error/dplyr:::mutate_error>
Error in `mutate()`:
! Problem while computing `region.index = paste(region, mydollars("{{agg_number}}2"), sep = "\n")`.
ℹ The error occurred in group 1: region = "North".
Caused by error in `x * scale`:
! non-numeric argument to binary operator
---
Backtrace:
  1. global treemap_index1(df, region, district, sales)
 10. scales (local) mydollars("{{agg_number}}2")
 11. scales::dollar(...)
 12. scales::number(...)
 13. scales:::scale_cut(...)
 14. base::cut(...)
Run `rlang::last_trace()` to see the full context.

Если я заменю оскорбительный код, как показано ниже, в противном случае функция будет работать:

treemap_index2 <- function(df, category1, category2, agg_number){
  
  df_out <- df %>% 
    mutate("{{category2}}.index" := paste({{category2}}, mydollars({{agg_number}}), sep = "\n")) %>% 
    group_by({{category1}}) %>%
    mutate("{{agg_number}}2" := sum({{agg_number}}),
           "{{category1}}.index" := paste({{category1}}, 
                                          "Test String", # Temporarily replaced code
                                          sep = "\n")) %>%
    print()
  
  return(df_out)
  
}
treemap_index2(df, region, district, sales)

# A tibble: 6 × 6
# Groups:   region [2]
  region district      sales district.index       sales2 region.index        
  <chr>  <chr>         <dbl> <chr>                 <dbl> <chr>               
1 North  Dist-1         2000 "Dist-1\n$2 K"   1800003600 "North\nTest String"
2 South  Dist-2    300001600 "Dist-2\n$300 M" 2700002400 "South\nTest String"
3 North  Dist-3    600001200 "Dist-3\n$600 M" 1800003600 "North\nTest String"
4 South  Dist-4    900000800 "Dist-4\n$900 M" 2700002400 "South\nTest String"
5 North  Dist-5   1200000400 "Dist-5\n$1.2 B" 1800003600 "North\nTest String"
6 South  Dist-6   1500000000 "Dist-6\n$1.5 B" 2700002400 "South\nTest String"

Помощь приветствуется...

Я был бы признателен за руководство о том, как правильно передать новое имя переменной вспомогательной функции, и, поскольку я новичок в маскировании данных, квазурах, нестандартной оценке, любые другие комментарии о том, как это можно сделать лучше, приветствуются. Спасибо.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Адаптируя ответ Лайонела Генри (@LionelHenry), можно использовать rlang::englue и местоимение .data следующим образом:

library(scales)
library(tidyverse)

treemap_index1 <- function(df, category1, category2, agg_number) {
  df %>%
    mutate("{{category2}}.index" := paste({{ category2 }}, mydollars({{ agg_number }}), sep = "\n")) %>%
    group_by({{ category1 }}) %>%
    mutate(
      "{{agg_number}}2" := sum({{ agg_number }}),
      "{{category1}}.index" := paste(
        {{ category1 }},
        mydollars(.data[[rlang::englue("{{agg_number}}2")]]),
        sep = "\n"
      )
    )
}

treemap_index1(df, region, district, sales)
#> # A tibble: 6 × 6
#> # Groups:   region [2]
#>   region district      sales district.index       sales2 region.index 
#>   <chr>  <chr>         <dbl> <chr>                 <dbl> <chr>        
#> 1 North  Dist-1         2000 "Dist-1\n$2 K"   1800003600 "North\n$2 B"
#> 2 South  Dist-2    300001600 "Dist-2\n$300 M" 2700002400 "South\n$3 B"
#> 3 North  Dist-3    600001200 "Dist-3\n$600 M" 1800003600 "North\n$2 B"
#> 4 South  Dist-4    900000800 "Dist-4\n$900 M" 2700002400 "South\n$3 B"
#> 5 North  Dist-5   1200000400 "Dist-5\n$1.2 B" 1800003600 "North\n$2 B"
#> 6 South  Dist-6   1500000000 "Dist-6\n$1.5 B" 2700002400 "South\n$3 B"

Это похоже на то, что мне было нужно. Я еще не пробовал, но ваш ответ и ссылка на @LionelHenry очень полезны. Спасибо.

wackojacko1997 05.01.2023 21:23

Другие вопросы по теме