Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

map a user-facing title to a backend name #450

Open
Tracked by #4
jgunstone opened this issue Sep 28, 2023 · 0 comments
Open
Tracked by #4

map a user-facing title to a backend name #450

jgunstone opened this issue Sep 28, 2023 · 0 comments

Comments

@jgunstone
Copy link
Contributor

jgunstone commented Sep 28, 2023

Is your feature request related to a problem? Please describe.
often when developing short-hand names are used, they don't contain spaces and are selected for ease of writing code.
when displaying results to a user the backend names are often mapped to user facing titles.
it would be great if ipydatagrid facilitated this.

Describe the solution you'd like
in ipyautoui we implemented something that does this - ipyautoui requires a schema which gives the user the opportunity to define a title. we override DataGrid with AutoGrid and in the __init__ we check if titles are present and update the dataframe before setting
https://github.com/maxfordham/ipyautoui/blob/782955ed379cd2b4f53b0ec0de74557813c2e80e/src/ipyautoui/custom/autogrid.py#L667-L696
something like this:
https://github.com/maxfordham/ipyautoui/blob/782955ed379cd2b4f53b0ec0de74557813c2e80e/src/ipyautoui/custom/autogrid.py#L432-L438

in autoui we care mostly about the jsonable value so we have a records property which does the mapping back to name rather than title.

it would be good if we could unpick some of this functionality and add it to ipydatagrid

Describe alternatives you've considered
when I looked at this again i thought that it might actually be better to use renderers rather than actually changing the underlying data

i.e.

import pandas as pd
from ipydatagrid import DataGrid, TextRenderer, Expr

def map_name(cell):
    map_ = {'a': 'Title A', 'b': 'Title B'}
    return map_[cell.value]

df = pd.DataFrame({"a":[1,2], "b": [3,4]})
hr = TextRenderer(text_value=Expr(map_name))
gr = DataGrid(df, header_renderer=hr)
gr

image

I could imagine adding a map_name_title trait which automatically applies this renderer on_change... ? this is good as you don't need to change the underlying dataframe.
the issues I see with this are:

  • we're taking control of the header_renderer making it unavailable to the user. it would be better if it could be done independently of that?
  • I don't know if this can be made to work with a multi-index title ?

Additional context
I was having a poke around thinking about where this could be best added to ipydatagrid...
pandas defines the schema like this:
https://specs.frictionlessdata.io/table-schema/
which explicitly supports a title (and description which would be great as a column heading tooltip!)
but unfortunately i don't think there is a way of add these metadata fields to a pandas dataframe object.

the main issue that i see is that the setting of the dataframe is the only required field. setting the dataframe happens first (before other traits are set) :

def __init__(self, dataframe, index_name=None, **kwargs):
# Setting default index name if not explicitly
# set by the user.
self._index_name = index_name
self.data = dataframe
super().__init__(**kwargs)
self._cell_click_handlers = CallbackDispatcher()
self._cell_change_handlers = CallbackDispatcher()
self.on_msg(self.__handle_custom_msg)

this then creates the schema:
@staticmethod
def generate_data_object(dataframe, guid_key="ipydguuid", index_name="key"):
dataframe[guid_key] = pd.RangeIndex(0, dataframe.shape[0])
# Renaming default index name from 'index' to 'key' on
# single index DataFrames. This allows users to use
# 'index' as a column name. If 'key' exists, we add _x
# suffix to id, where { x | 0 <= x < inf }
if not isinstance(dataframe.index, pd.MultiIndex):
if index_name in dataframe.columns:
index = 0
new_index_name = f"{index_name}_{index}"
while new_index_name in dataframe.columns:
index += 1
new_index_name = f"{index_name}_{index}"
dataframe = dataframe.rename_axis(new_index_name)
else:
dataframe = dataframe.rename_axis(index_name)
schema = pd.io.json.build_table_schema(dataframe)
reset_index_dataframe = dataframe.reset_index()
data = reset_index_dataframe.to_dict(orient="records")
# Check for multiple primary keys
key = reset_index_dataframe.columns[: dataframe.index.nlevels].tolist()
num_index_levels = len(key) if isinstance(key, list) else 1

I think it would be good if the schema was also a trait - if not given it is defined by the dataframe, otherwise it can be used to add additional metadata about the dataframe... with some logic to ensure the 2 things are consistent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant