-
Notifications
You must be signed in to change notification settings - Fork 9
/
funky_heatmap.R
186 lines (183 loc) Β· 7.1 KB
/
funky_heatmap.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#' Generate a funky heatmaps for benchmarks
#'
#' Allows generating heatmap-like visualisations for benchmark data
#' frames. Funky heatmaps can be fine-tuned by providing annotations of the
#' columns and rows, which allows assigning multiple palettes or geometries
#' or grouping rows and columns together in categories.
#'
#' @param data A data frame with items by row and features in the columns.
#' Must contain one column named `"id"`.
#'
#' @param column_info A data frame describing which columns in `data` to
#' plot. This data frame should contain the following columns:
#'
#' * `id` (`character`): The corresponding column name in `data`.
#'
#' * `name` (`character`): A label for the column. If `NA` or `""`,
#' no label will be plotted. If this column is missing, `id` will
#' be used to generate the `name` column.
#'
#' * `geom` (`character`): The geom of the column. Must be one of:
#' `"funkyrect"`, `"circle"`, `"rect"`, `"bar"`, `"pie"`, `"text"` or `"image"`.
#' For `"text"`, the corresponding column in `data` must be a `character`.
#' For `"pie"`, the column must be a list of named numeric vectors.
#' For all other geoms, the column must be a `numeric`.
#'
#' * `group` (`character`): The grouping id of each column, must match with
#' `column_groups$group`. If this column is missing or all values are `NA`,
#' columns are assumed not to be grouped.
#'
#' * `palette` (`character`): Which palette to colour the geom by.
#' Each value should have a matching value in `palettes$palette`.
#'
#' * `width`: Custom width for this column (default: 1).
#'
#' * `overlay`: Whether to overlay this column over the previous column.
#' If so, the width of that column will be inherited.
#'
#' * `legend`: Whether or not to add a legend for this column.
#'
#' * `hjust`: Horizontal alignment of the bar, must be between \[0,1\]
#' (only for `geom = "bar"`).
#'
#' * `vjust`: Vertical alignment of the label, must be between \[0,1\]
#' (only for `geom = "text"`).
#'
#' * `size`: Size of the label, must be a numeric value
#' (only for `geom = "text"`).
#'
#' * `label`: Which column to use as a label (only for `geom = "text"`).
#'
#' * `directory`: Which directory to use to find the images (only for `geom = "image"`).
#'
#' * `extension`: The extension of the images (only for `geom = "image"`).
#'
#' * `options` (`list` or `json`): Any of the options above. Any values in this
#' column will be spread across the other columns. This is useful for
#' not having to provide a data frame with 1000s of columns.
#' This column can be a json string.
#'
#' @param row_info A data frame describing the rows of `data`.
#' This data should contain two columns:
#'
#' * `id` (`character`): Corresponds to the column `data$id`.
#'
#' * `group` (`character`): The group of the row.
#' If all are `NA`, the rows will not be split up into groups.
#'
#' @param column_groups A data frame describing of how to group the columns
#' in `column_info`. Can consist of the following columns:
#'
#' * `group` (`character`): The corresponding group in `column_info$group`.
#' * `palette` (`character`, optional): The palette used to colour the
#' column group backgrounds.
#' * `level1` (`character`): The label at the highest level.
#' * `level2` (`character`, optional): The label at the middle level.
#' * `level3` (`character`, optional): The label at the lowest level
#' (not recommended).
#'
#' @param row_groups A data frame describing of how to group the rows
#' in `row_info`. Can consist of the following columns:
#'
#' * `group` (`character`): The corresponding group in `row_info$group`.
#' * `level1` (`character`): The label at the highest level.
#' * `level2` (`character`, optional): The label at the middle level.
#' * `level3` (`character`, optional): The label at the lowest level
#' (not recommended).
#'
#' @param palettes A named list of palettes. Each entry in `column_info$palette`
#' should have an entry in this object. If an entry is missing, the type
#' of the column will be inferred (categorical or numerical) and one of the
#' default palettes will be applied. Alternatively, the name of one of the
#' standard palette names can be used:
#'
#' * `numerical`: `"Greys"`, `"Blues"`, `"Reds"`, `"YlOrBr"`, `"Greens"`
#' * `categorical`: `"Set3"`, `"Set1"`, `"Set2"`, `"Dark2"`
#'
#' @param position_args Sets parameters that affect positioning within a
#' plot, such as row and column dimensions, annotation details, and the
#' expansion directions of the plot. See `position_arguments()` for more information.
#'
#' @param scale_column Whether or not to apply min-max scaling to each
#' numerical column.
#'
#' @param add_abc Whether or not to add subfigure labels to the different
#' columns groups.
#'
#' @param removed_entries Which methods to not show in the rows. Missing methods
#' are replaced by a "Not shown" label.
#'
#' @param col_annot_offset DEPRECATED: use `position_args = position_arguments(col_annot_offset = ...)` instead.
#' @param col_annot_angle DEPRECATED: use `position_args = position_arguments(col_annot_angle = ...)` instead.
#' @param expand DEPRECATED: use `position_args = position_arguments(expand_* = ...)` instead.
#'
#' @importFrom ggforce geom_arc_bar geom_circle geom_arc
#' @importFrom cowplot theme_nothing
#'
#' @returns A ggplot. `.$width` and `.$height` are suggested dimensions for
#' storing the plot with [ggsave()].
#'
#' @export
#'
#' @examples
#' library(tibble, warn.conflicts = FALSE)
#'
#' data("mtcars")
#'
#' data <- rownames_to_column(mtcars, "id")
#'
#' funky_heatmap(data)
funky_heatmap <- function(
data,
column_info = NULL,
row_info = NULL,
column_groups = NULL,
row_groups = NULL,
palettes = NULL,
position_args = position_arguments(),
scale_column = TRUE,
add_abc = TRUE,
removed_entries = NULL,
col_annot_offset,
col_annot_angle,
expand) {
# validate input objects
data <- verify_data(data)
column_info <- verify_column_info(column_info, data)
row_info <- verify_row_info(row_info, data)
column_groups <- verify_column_groups(column_groups, column_info)
row_groups <- verify_row_groups(row_groups, row_info)
palettes <- verify_palettes(palettes, column_info, data)
# check deprecated arguments
if (!missing(col_annot_offset)) {
warning("Argument `col_annot_offset` is deprecated. Use `position_arguments(col_annot_offset = ...)` instead.")
position_args$col_annot_offset <- col_annot_offset
}
if (!missing(col_annot_angle)) {
warning("Argument `col_annot_angle` is deprecated. Use `position_arguments(col_annot_angle = ...)` instead.")
position_args$col_annot_angle <- col_annot_angle
}
if (!missing(expand)) {
warning("Argument `expand` is deprecated. Use `position_arguments(expand_* = ...)` instead.")
for (name in names(expand)) {
position_args[[paste0("expand_", name)]] <- expand[[name]]
}
}
# todo: add column groups to verify_palettes
geom_positions <- calculate_geom_positions(
data,
column_info,
row_info,
column_groups,
row_groups,
palettes,
position_args,
scale_column,
add_abc,
removed_entries
)
compose_ggplot(
geom_positions,
position_args
)
}