Closed tylerlittlefield closed 4 years ago
I've added an experimental branch for this here in explore-s3
, which basically lets you do this:
devtools::load_all()
df <- structure(
list(
parent_id = c("Bob", "Bob", "Bob", "Bob", "Angelica"),
child_id = c("Bob", "Angelica", "Eliza", "Peggy", "John"),
child = c("Bob", "Angelica", "Eliza", "Peggy", "John"),
node_type = c("gen1", "gen2", "gen2", "gen2", "gen3"),
link = c("ROOT", "daughter", "daughter", "daughter", "son"),
height = c("100 cm", "100 cm", "90 cm", "50 cm", "10 cm"),
age = c("60 yo", "30 yo", "25 yo", "10 yo", "0.5 yo")
),
row.names = c(NA, -5L),
class = "data.frame"
)
hierplane(df, "Family Tree", hierplane_settings(attributes = c("height", "age")))
hierplane("Sam likes boats")
This would mean that the .data
param would basically be described as:
Accepts either a string or a
data.frame
with hierarchical features.
This should work but I think the documentation will need to be very clear that if a string is passed, spacy will be used. I am leaning slightly towards hierplane_spacy()
in case we want to allow additional models/methods to interpret a string. Perhaps hierplane()
can take another param for preprocessing method (tho for now it's just spacy lol).
Just trying to think of ways to avoid future rework :D
Ah, good point about character objects having the potential to be interpreted differently, e.g. if we wanted to do something other than use spacyr when given a string. Still, I don't know how I feel about adding a function every time we find a new "thing" that hierplane can use. I like that we have a single function + render/output for shiny.
What if we created object functions, like hp_<special>
:
hp_dataframe()
hp_spacyr()
hp_json()
So the syntax would be something like:
hierplane(
.data = hp_dataframe(df),
title = "Family Tree",
settings = hierplane_settings(attributes = c("height", "age")) # still conflicted about this function name haha
)
hierplane(
.data = hp_spacyr("Sam likes boats")
)
Then the documentation would say that hierplane only accepts a hierplane object, see the hp_
family. These hp_
functions would just take data and serve as "gatekeepers" for providing usable/hierplane ready data.
Do you like use_spacyr("Sam likes boats")
? We can do what caret/tidymodels do and have a script for handlers for each special input (like what we have for spacy now).
Are you saying something like this?
hierplane(.data = use_spacyr("Sam likes boats"))
ye
And then use_dataframe()
?
what does use_dataframe()
do again??
use_spacyr()
should get the data ready in the format that can be used in build_tree
I actually prefer the hp_
prefix so we can explain these functions as functions that create hierplane objects.
In this example, hp_dataframe()
would require a dataframe, title, and settings. It would do all kinds of manipulations/checks to make sure this dataframe can be used in hierplane. Then we would remove title/settings from the hierplane function (which I admittedly added in the s3 branch).
In one hypothetical API we have:
hierplane()
for shiny/rstudio viewerhierplaneOutput()
/ renderHierplane()
for shinyhp_
for creating hierplane objectshierplane_settings()
??? maybe we don't even need it if we embrace hp_
functions, settings could be defined there, e.g. hp_spacyr
doesn't even need settings, we handle that for the userIn another hypothetical API we have:
hierplane_()
for shiny/rstudio viewerhierplaneOutput()
/ renderHierplane()
for shinyhierplane_settings()
needed because we don't want to cram a bunch of settings in the hierplane_
functions.In the first API, the workflow is:
In the second API, the workflow is:
What does a hierplane object look like? A list containing tree
and theme
(what's in hierplane
right now)?
A hierplane object would always output the necessary json. On master, hierplane always ends up calling build_tree(.data, title, settings)
, which returns json. So no change there, the only difference between both possible APIs, is:
hierplane_
functions to handle different types of hierplaneshp_
functions to handle different types of hierplanesIn point 1, the hierplane_
functions are doing two things, creating a hierplanes and handling special types of hierplane data. In point 2, hierplane
does one thing (generate hierplanes) and hp_
functions do one thing (create hierplane objects).
I think we can stick with what we have now. But I will give point 2 a shot later, just so we can compare things. Since we only have two functions, translating won't be a huge undertaking.
If I am interpreting what you're saying correctly, I think I'm completely aligned. What I think you're saying is that the hierplane functions will only create the JSON, and the function that creates the actual widget will be a separate function. I think this makes a lot of sense. Essentially we will be extracting the creation of the tree out of the hierplane function, correct?
Essentially we will be extracting the creation of the tree out of the hierplane function
Yes, that's what I am thinking, except that there is only one hierplane function for rendering hierplanes.
The hierplane()
function only has one job and it's to render the hierplane. The hp_
functions only have one job and it's to create hierplane ready data depending on the input, e.g. hp_spacyr
is used for translating spacyr input to hierplane ready json.
Ok yea I think we are on the same page!
So to render the hierplane (i.e. make a widget) it would look something like this?
hierplane(hp_dataframe(df, title, settings), theme)
hierplane(hp_spacyr(txt, settings), theme)
Exactly! I think just like you decoupled spacyr from the package, we are now trying to decouple the input to json logic from the hierplane function. Mentally this just seems cleaner or more "neat" to me in that the API would be:
hierplane()
/renderHierplane()
/hierplaneOutput()
= render hierplane!hp_
create hierplane ready data based on different input dataOkay, now time to review the style maps :D
Do we prefer the current version:
Or maybe something like: