r4fun / hierplane

🌳 Hierplane for R
https://r4fun.github.io/hierplane/
Other
9 stars 0 forks source link

Hierplane fails with tibbles #18

Closed tylerlittlefield closed 4 years ago

tylerlittlefield commented 4 years ago

It works regular data.frame so we need to figure out how to get it to work with tibble:

devtools::load_all()

df <- tibble::tribble(
  ~parent_id,  ~child_id,    ~child,      ~node_type,     ~link,      ~height,  ~age,
  "Bob",       "Bob",        "Bob",       "gen1",         "ROOT",     "100 cm", "60 yo",
  "Bob",       "Angelica",   "Angelica",  "gen2",         "daughter", "100 cm", "30 yo",
  "Bob",       "Eliza",      "Eliza",     "gen2",         "daughter", "90 cm",  "25 yo",
  "Bob",       "Peggy",      "Peggy",     "gen2",         "daughter", "50 cm",  "10 yo",
  "Angelica",  "John",       "John",      "gen3",         "son",      "10 cm",  "0.5 yo"
)

hierplane(df, settings = construct_settings(attributes = c("height", "age")))
mathidachuk commented 4 years ago

What do you have in mind for a fix? Can I just add as.data.frame() to build_tree()? lol

tylerlittlefield commented 4 years ago

We could, but usually when tibble fails, it's because we're doing something we shouldn't, tibble is more strict than data.frame:

Compared to a data.frame, tibbles are more strict: they never do partial matching, and they will generate a warning if the column you are trying to access does not exist.

So we will probably want to find out where this is coming from and resolve. I just haven't taken a look yet.

mathidachuk commented 4 years ago

I found the culprit: image

This is essentially what is happening in parse root:

parse_root <- function(x, settings) {
  list(
    id = x[x[[settings$link]] %in% settings$root_tag, settings$child_id],
    dat = x[x[[settings$link]] %in% settings$root_tag, ]
  )
}

The integrity of a tibble structure is maintained when you subset a single value using base R syntax. In the example above, root$id is a tibble, when the expectation of root is a character/string. I suppose it makes sense that tibble maintains the structure when subsetting but I don't love it cuz it conflicts with how base R dataframes behave, but it will not kill me to wrap x[x[[settings$link]] %in% settings$root_tag, settings$child_id] in as.character().

What do you think?

tylerlittlefield commented 4 years ago

Oh yeah, I always forget about drop, i.e. iris[1, "Sepal.Width", drop = FALSE]. I think as.character works (unless we want to preserve type), in which case you could use [[:

df <- iris
df_tbl <- tibble::as_tibble(iris)
df[[1, "Sepal.Length"]]
df_tbl[[1, "Sepal.Length"]]
mathidachuk commented 4 years ago

more square brackets............ 😖

tylerlittlefield commented 4 years ago

Your call, I don't think the type matters... so as.character works.

tylerlittlefield commented 4 years ago

Closed #23