Search code examples
rpowerbirlang

PowerBI R Script Runtime Error,Prefixing UQ() with the rlang namespace is deprecated as of rlang 0.3.0


Below is the reproducible code which needs to be pasted in PowerBI R script visualization. I'm making some customizations to the default process_map object.

The visual works on my current desktop but gives out error when published to PowerBI Web.

# The following code to create a dataframe and remove duplicated rows is always executed and acts as a preamble for your script: 

# dataset <- data.frame(Column1)
# dataset <- unique(dataset)

# Paste or type your script code here:
library(bupaR)
library(DiagrammeR)
library(tidyverse)
library(lubridate)


# convert to proper date


processMap <- patients %>%
  process_map(sec = performance(median, "hours")
              ,type = frequency("relative_case")
              ,type_edges = frequency("absolute_case")
              ,rankdir = "LR"
              ,layout = layout_pm(edge_weight = TRUE)
              ,fixed_edge_width = F
              ,render = F
  )

# customisation(label, color, font)
processMap$nodes_df$label <- stringr::str_replace_all(processMap$nodes_df$label, c('ARTIFICIAL_START' = 'Start', 'ARTIFICIAL_END' = 'End'))
processMap$nodes_df$color <- stringr::str_replace_all(processMap$nodes_df$color, c('chartreuse4' = '#769e00', 'brown4' = '#7a0f2d'))
processMap$nodes_df$fontcolor <- stringr::str_replace_all(processMap$nodes_df$fontcolor, c('chartreuse4' = '#769e00', 'brown4' = '#7a0f2d'))
processMap$nodes_df$fontname <- stringr::str_replace_all(processMap$nodes_df$fontname, c('Arial' = 'Calibri'))
processMap$edges_df$fontname <- stringr::str_replace_all(processMap$edges_df$fontname, c('Arial' = 'Calibri'))
# change edge with
processMap$edges_df$penwidth <- scales::rescale(processMap$edges_df$penwidth, to = c(0.5, 4)) 

# custom duration edges
edges_label <- processMap$edges_df$label
tmp <- regmatches(edges_label, gregexpr("\\(.*?\\)", edges_label))
tmp <- gsub("[\\(\\)]", "", tmp)
tmp <- stringr::str_replace_all(tmp, c('character0' = '0', ' hours'=''))
tmp <- as.numeric(tmp)*60*60
tmp <- lubridate::as.duration(tmp)
tmp <- regmatches(tmp, gregexpr("\\(.*?\\)", tmp))
tmp <- gsub("[\\(\\)]", "", tmp)
edges_label_duration <- stringr::str_replace_all(tmp, c('character0' = '<1 hour'))
edges_label_count_absolute_case <- gsub("\n.*","",edges_label)
edges_label_clean <- paste0(edges_label_count_absolute_case, '\n',edges_label_duration)
 
# remove those which should have no hour()
correct_label <- gsub("\n.*","",edges_label_clean[!grepl("hour", edges_label)])
edges_label_clean[!grepl("hour", edges_label)] <- correct_label
# assign to process object
processMap$edges_df$label <- edges_label_clean

DiagrammeR::export_graph(graph = processMap, file_type = 'png', file_name = 'processMap.png')

Below is the visual output in PowerBI desktop Visual output in desktop

When published to the PowerBI portal, it gives the following error

Error in if (any(ind)) Encoding(x[ind]) <- "bytes" :
missing value where TRUE/FALSE needed
In addition: Warning message:
Prefixing `UQ()` with the rlang namespace is deprecated as of rlang 0.3.0.
Please use the non-prefixed form or `!!` instead.

# Bad:
rlang::expr(mean(rlang::UQ(var) * 100))

# Ok:
rlang::expr(mean(UQ(var) * 100))

# Good:
rlang::expr(mean(!!var * 100))


rlang's on desktop is rlang_0.4.10 while the PowerBI Web has a rlang_0.3.0


Solution

  • I ended up re-writing the customisation code so that there's no function within a function which is referenced by the error code below

    # Bad:
    rlang::expr(mean(rlang::UQ(var) * 100))
    

    I suspect the related function is this one

    regmatches(edges_label, gregexpr("\\(.*?\\)", edges_label))
    

    Couldn't really definitively say it's the case but anyways the updated code below generates no more error when published to PowerBI service/web.

    library(bupaR)
    library(DiagrammeR)
    library(tidyverse)
    library(lubridate)
    
    
    # convert to proper date
    
    
    processMap <- patients %>%
      process_map(sec = performance(median, "hours")
                  ,type = frequency("relative_case")
                  ,type_edges = frequency("absolute_case")
                  ,rankdir = "LR"
                  ,layout = layout_pm(edge_weight = TRUE)
                  ,fixed_edge_width = F
                  ,render = F
      )
    
    # customisation(label, color, font)
    processMap$nodes_df$label <- stringr::str_replace_all(processMap$nodes_df$label, c('ARTIFICIAL_START' = 'Start', 'ARTIFICIAL_END' = 'End'))
    processMap$nodes_df$color <- stringr::str_replace_all(processMap$nodes_df$color, c('chartreuse4' = '#769e00', 'brown4' = '#7a0f2d'))
    processMap$nodes_df$fontcolor <- stringr::str_replace_all(processMap$nodes_df$fontcolor, c('chartreuse4' = '#769e00', 'brown4' = '#7a0f2d'))
    processMap$nodes_df$fontname <- stringr::str_replace_all(processMap$nodes_df$fontname, c('Arial' = 'Calibri'))
    processMap$edges_df$fontname <- stringr::str_replace_all(processMap$edges_df$fontname, c('Arial' = 'Calibri'))
    # change edge with
    processMap$edges_df$penwidth <- scales::rescale(processMap$edges_df$penwidth, to = c(0.5, 4)) 
    
    # custom duration edges
    edges_label <- processMap$edges_df$label
    # extract within bracket
    tmp <- stringr::str_extract(string = edges_label,
                         pattern = "(?<=\\().*(?=\\))")
    tmp <- stringr::str_replace_all(tmp, c(' hours'=''))
    tmp[is.na(tmp)] <- '0'
    tmp <- as.numeric(tmp)*60*60
    tmp <- lubridate::as.duration(tmp)
    
    tmp <- stringr::str_extract(string = tmp,
                                pattern = "\\(.*?\\)")
    tmp[is.na(tmp)] <- '(<1 hour)'
    edges_label_duration <- tmp
    edges_label_count_absolute_case <- gsub("\n.*","",edges_label)
    edges_label_clean <- paste0(edges_label_count_absolute_case, '\n',edges_label_duration)
     
    # remove those which should have no hour()
    correct_label <- gsub("\n.*","",edges_label_clean[!grepl("hour", edges_label)])
    edges_label_clean[!grepl("hour", edges_label)] <- correct_label
    # assign to process object
    processMap$edges_df$label <- edges_label_clean
    
    DiagrammeR::export_graph(graph = processMap, file_type = 'png', file_name = 'processMap.png')