chop-cgtinformatics / ggswim Goto Github PK
View Code? Open in Web Editor NEWCreate swimmer plots with ggplot2
Home Page: https://chop-cgtinformatics.github.io/ggswim/
License: Other
Create swimmer plots with ggplot2
Home Page: https://chop-cgtinformatics.github.io/ggswim/
License: Other
There is currently a reference_event
argument for ggswim()
which has not been incorporated into the business logic.
The idea here is that if time
is not an integer/numeric value, i.e. Date/Date-time, that record swim lanes are centered automatically around a reference event from the event stream.
Example:
df <- tibble::tribble(
~subject_id, ~time, ~event,
1, "2020-01-01", "Infusion",
1, "2020-02-01", "CRS Grade 1",
1, "2020-03-01", "CRS Grade 2",
2, "2020-05-01", "Infusion",
2, "2020-06-01", "No CRS",
3, "2020-09-01", "Infusion",
3, "2020-10-01", "CRS Grade 3",
...
)
ggswim(...
reference_event = "infusion",
...
)
If a user needs to coerce or otherwise manipulate an argument while working inside of ggswim()
or add_marker()
, rendering should still work.
Because of how ggswim identifies and retrieves layer data, providing anything that isn't a specific variable name in data
will cause an error. This is due to the use of rlang::get_expr()
in the get_layer_data()
utility function:
Lines 28 to 41 in 9ab6a24
devtools::load_all(".")
patient_data <- ggswim::patient_data
patient_status <- patient_data$patient_status
adverse_events <- patient_data$adverse_events
medication_administration <- patient_data$medication_administration
patient_status |>
tidyr::pivot_longer(c(time_start, time_end)) |>
dplyr::mutate(.by = subject_id,
time_sorting = sum(value)) |>
dplyr::arrange(cohort, time_sorting) |>
dplyr::mutate(subject_id = factor(subject_id, levels = unique(subject_id))) |>
ggswim(data = patient_status,
mapping = aes(x = value,
y = subject_id,
fill = cohort)) +
add_marker(data = adverse_events,
mapping = aes(x = time_of_event,
y = subject_id,
color = factor(adverse_event_name), # This will cause the error
shape = adverse_event_name),
size = 5)
Downstream when the logic gets to get_layer_data()
, we reference mapping
from the top level ggswim function to identify different aesthetics supplied by the user. By using factor(adverse_event_name)
above for color
, accessing mapping
returns:
Aesthetic mapping:
* `x` -> `time_of_event`
* `y` -> `subject_id`
* `colour` -> `factor(adverse_event_name)`
* `shape` -> `adverse_event_name`
While it would be somewhat simple to use regex to drop parentheses, this may not account for all circumstances. To note, a similar issue happens in ggswimlane
as well.
Before submitting this issue, please check and verify below that the submission meets the below criteria:
Sometimes users may not want to specify everything in one ggswim()
command, and in those cases it may be helpful to allow ggplot()
-esque function additions to tack on more layers
Develop new functions capable of tacking on new geom layers like below:
ggswim(my_data, time = time, events = event) +
add_marker() +
add_lane()
I tried to install ggswim today and I ran into a problems caused by {renv
}. renv::restore()
can't install all the dependencies because I run into:
#include <png.h>
^~~~~~~
1 error generated.
make: *** [devSVG.o] Error 1
ERROR: compilation failed for package ‘vdiffr’
I manually installed packages with renv::install()
and I am able to bulid the package but the vignettes are missing. I installed devtools and tried devtools::install(build_vigngettes = TRUE)
and the package installs but the vignettes are missing.
Is there an ETA on the CRAN release?
When users submit markers as emojis, we expect them to be rendered appropriately.
For deployed applications to Posit Connect and Shinyapps.io, there is a known issue where emojis will not render in the display, instead showing empty boxes (displayed below).
For emojis to render locally, a few things can be done:
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE,
dev='ragg_png')
...
For shiny
, it seems graphics device settings and a library(ragg)
call is enough.
One possible solution is to install the libagg-dev
package onto the server that hosts the application.
Before submitting this issue, please check and verify below that the submission meets the below criteria:
ggswim functions should come with pre-determined default values for best visuals
Consider adding default values for ggswim()
and add_marker()
to help with arguments like size
, label
borders, column sizes, etc.
ggswim()
will construct the lanes, and each marker will be added separately with calls to + add_marker()
In trial data, event streams may also need to include "groups" such as in the case of identifying treatment groups.
This should be optional, and presented in the event stream similar to below:
df <- tibble::tribble(
~subject_id, ~time, ~event, ~treament_group,
1, 0, "Infusion", "Cohort A",
1, 2, "CRS Grade 1", "Cohort A",
1, 3, "CRS Grade 2", "Cohort A",
1, 4, "CRS Grade 1", "Cohort A",
1, 5, "No CRS", "Cohort A",
1, 6, "Last Follow Up", "Cohort A",
2, 0, "Infusion", "Cohort B",
2, 1, "CRS Grade 1", "Cohort B",
2, 4, "CRS Grade 2", "Cohort B",
2, 7, "CRS Grade 1", "Cohort B",
2, 8, "No CRS", "Cohort B",
2, 9, "Last Follow Up", "Cohort B",
...
)
With an additional optional argument in ggswim()
like "group = ___".
At least for now, one of the main data structures to get ggswim()
to work uses the "event stream". This may not be readily available to users, or apparent and so documentation should be provided to help them.
To guide users through how to structure and shape their data, we should provide an example using a readily available and recognizable dataset: survival::pbcseq
. Below is a sample of the raw dataset:
> tibble::tibble(survival::pbcseq)
# A tibble: 1,945 × 19
id futime status trt age sex day ascites hepato spiders edema bili chol albumin alk.phos ast platelet protime stage
<int> <int> <int> <int> <dbl> <fct> <int> <int> <int> <int> <dbl> <dbl> <int> <dbl> <int> <dbl> <int> <dbl> <int>
1 1 400 2 1 58.8 f 0 1 1 1 1 14.5 261 2.6 1718 138 190 12.2 4
2 1 400 2 1 58.8 f 192 1 1 1 1 21.3 NA 2.94 1612 6.2 183 11.2 4
3 2 5169 0 1 56.4 f 0 0 1 1 0 1.1 302 4.14 7395 114. 221 10.6 3
4 2 5169 0 1 56.4 f 182 0 1 1 0 0.8 NA 3.6 2107 140. 188 11 3
5 2 5169 0 1 56.4 f 365 0 1 1 0 1 NA 3.55 1711 144. 161 11.6 3
6 2 5169 0 1 56.4 f 768 0 1 1 0 1.9 NA 3.92 1365 144. 122 10.6 3
7 2 5169 0 1 56.4 f 1790 1 1 1 0.5 2.6 230 3.32 1110 132. 135 11.3 3
8 2 5169 0 1 56.4 f 2151 1 1 1 1 3.6 NA 2.92 996 132. 100 11.5 3
9 2 5169 0 1 56.4 f 2515 1 1 1 1 4.2 NA 2.73 860 146. 103 11.5 3
10 2 5169 0 1 56.4 f 2882 1 1 1 1 3.6 244 2.8 779 119 113 11.5 3
# ℹ 1,935 more rows
# ℹ Use `print(n = ...)` to see more rows
Here we could consider that current ggswim()
arguments map to id = id
, day = time
, acites
/hepato
/spiders
/edema
comprise binary events
, and status = lanes
.
ggswim should come with its own preferred themeing function: theme_ggswim()
.
Things it should include are:
Currently, the ggswim()
API accepts lanes
and lane_colors
as separate vectors. Instead, it should accept a named list, similar to how markers
currently behaves. This can also allow lanes
and lane_colors
to be combined into one argument where each lane equals a color. If no color is given, default colors from ggplot should be applied.
Current API:
df |>
ggswim(id = subject_id,
time = time,
events = event,
reference_event = "Infusion",
emoji_or_shape = "emoji",
markers = markers_emoji,
lanes = c("CRS Grade 1", "CRS Grade 2", "CRS Grade 3", "CRS Grade 4", "CRS Grade 5", "No CRS"),
lane_colors = c("yellow", "orange", "pink", "red", "black", "gray"),
title = "My Emoji Swim Plot",
xlab = "Time",
ylab = "Subject ID",
legend_title = "My Legend Title")
Proposed API:
df |>
ggswim(id = subject_id,
time = time,
events = event,
reference_event = "Infusion",
emoji_or_shape = "emoji",
markers = markers_emoji,
lanes = list(
"No CRS" = "gray",
"CRS Grade 1" = "yellow",
"CRS Grade 2" = "orange",
"CRS Grade 3" = "pink",
"CRS Grade 4" = "red",
"CRS Grade 5" = "black"
),
title = "My Emoji Swim Plot",
xlab = "Time",
ylab = "Subject ID",
legend_title = "My Legend Title")
Additionally, the first lane should be the default/generic one that gets applied in the absence of lane designation in the event stream (i.e. in rows where markers get declared or at the beginning of the data when nothing has been declared yet).
The default colors for a ggswim plot, like those in the example README, result in color points that are lost in the fill lanes because they are the same colors:
library(ggswim)
patient_status |>
ggswim(aes(time_sorting, subject_id, fill = cohort)) +
add_marker(data = adverse_events,
aes(x = time_of_event,
y = subject_id,
colour = adverse_event_name,
shape = adverse_event_name),
size = 8)
We need to either define or have smarter definition for colors so this isn't the default behavior.
ggswim()
and add_marker()
should be able to handle data inputs as closely as possible to how ggplot2
does out of the box.
Due to some manipulations which require checking UI for mapping aesthetics, an internal utility function called get_layer_data()
fails due to dependence on rlang::get_expr()
.
The following code can reproduce the bug:
devtools::load_all(".")
patient_data$patient_status |>
tidyr::pivot_longer(c(time_start, time_end)) |>
ggswim(data = patient_data$patient_status,
mapping = aes(x = value,
y = subject_id,
fill = cohort)) +
add_marker(data = patient_data$adverse_events,
mapping = aes(x = time_of_event,
y = subject_id,
color = factor(adverse_event_name), # The bug occurs here
shape = adverse_event_name),
size = 5)
Lines 30 to 38 in fb28dde
The point of failure is shown above, due to coercing adverse_event_name
and providing more that rlang
sees than just the name of the variable.
Before submitting this issue, please check and verify below that the submission meets the below criteria:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.