rtidyverseevallapplycomplexheatmap

Make a list of arguments for a function from a character vector


I am making a ComplexHeatmap and I want to show multiple row annotations (i.e., multiple named arguments inside the rowAnnotation function) corresponding to columns of information from my original data. What I am doing now, having 7 columns of information:

library(ComplexHeatmap)


# sample dataframe
EF_data <- data.frame(Package = sample(1:10, 10),
                      Information = sample(1:10, 10),
                      Atoms = sample(1:10, 10),
                      Measure = sample(1:10, 10),
                      Filter = sample(1:10, 10),
                      Analysis = sample(1:10, 10),
                      Averaging = sample(1:10, 10))


# what i'm doing now
left_an_gp <- gpar(fontsize = 8)

left_an = rowAnnotation(Package = anno_text(EF_data$Package, gp = left_an_gp),
                        Information = anno_text(EF_data$Information, gp = left_an_gp),
                        Atoms = anno_text(EF_data$Atoms, gp = left_an_gp),
                        Measure = anno_text(EF_data$Measure, gp = left_an_gp),
                        Filter = anno_text(EF_data$Filter, gp = left_an_gp),
                        Analysis = anno_text(EF_data$Analysis, gp = left_an_gp),
                        Averaging = anno_text(EF_data$Averaging, gp = left_an_gp),
                        gap = unit(0.5, "mm"))

# and then draw the heatmap with the data from a matrix etc

What I want to do is to generate the rowAnnotation using, for example, the columns(EF_data) character vector. Every argument inside rowAnnotate is the same except for its name and the name of the column after the $, so I wonder if there is a more compressed way of doing this. I have tried to search for one but I guess I'm not using the right terminology to find an approach.

I imagine it would be something like:

apply(
  eval(
    "{} = anno_text(EF_data${}, gp = left_an_gp)"
    ), 
  columns(EF_data)
)

but I don't quite know how to even start to try to do it correctly.


Solution

  • You don't need to resort to parsing and evaluating text. Instead, you can build the arguments to the call using lapply and invoke the function with do.call

    args <- lapply(EF_data, function(x) row_anno_text(x, gp = left_an_gp))
    args <- setNames(args, names(EF_data))
    args$gap <- unit(0.5, "mm")
    left_an <- do.call(rowAnnotation, args)
    
    left_an
    #> A HeatmapAnnotation object with 7 annotations
    #>   name: heatmap_annotation_0 
    #>   position: row 
    #>   items: 10 
    #>   width: 24.9681777777778mm 
    #>   height: 1npc 
    #>   this object is subsettable
    #> 
    #>         name annotation_type color_mapping              width
    #>      Package     anno_text()               3.13831111111111mm
    #>  Information     anno_text()               3.13831111111111mm
    #>        Atoms     anno_text()               3.13831111111111mm
    #>      Measure     anno_text()               3.13831111111111mm
    #>       Filter     anno_text()               3.13831111111111mm
    #>     Analysis     anno_text()               3.13831111111111mm
    #>    Averaging     anno_text()               3.13831111111111mm
    

    Created on 2022-05-09 by the reprex package (v2.0.1)