mwouts / itables

Pandas DataFrames as Interactive DataTables
https://mwouts.github.io/itables/
MIT License
740 stars 55 forks source link

Leveraging panda's to_html() function #63

Closed vincent-grosbois closed 2 years ago

vincent-grosbois commented 2 years ago

Hello it seems that itable doesn't support displaying dataframes with multiindex, whereas datatables could support it . This seems to come from the fact that _make_header function only works for non-multiindex columns. However it seems that Pandas's dataframe to_html() function is able to correctly render multiindex columns, using much more complex logic. It also seems that using the raw datatables lib over the html pandas dataframe will indeed correctly convert the dataframe.

So, my question is the following: would it be possible to add a functionality so that the "base table HTML" for the dataframe is not generated with itables code but with pandas's to_html code ? This would also allow that styling defined in pandas is preserved

thanks!

mwouts commented 2 years ago

Hi @vincent-grosbois , thank you for asking.

Well indeed datatables.net can easily render an HTML table - this is even their zero configuration example, so what you suggest could be an option.

I think I initially tried this (I mean, use pandas' to_html function) for itables, but then I decided to encode manually the table because datables.net was much faster with the data passed as a JSON object rather than as an HTML table.

I agree with your two other points, i.e.

mwouts commented 2 years ago

Until version 0.4.1, we were using .to_html() to generate the table header, cf. this commit

I don't advice to revert to version 0.4.1 because we fixed many other issues since then, but I'll see if I can improve the rendering of multiindex columns by reverting to using .to_html() for the header.

mwouts commented 2 years ago

Hi @vincent-grosbois , could you please give a try to this development version, and confirm that it works fine for you?

pip install git+https://github.com/mwouts/itables.git@improve_multiindex_columns

Thanks

qqdaiyu55 commented 2 years ago

My implementation leveraging to_html(), supports search result highlight

def show_table(df):
    import uuid
    from IPython.display import display, HTML, Javascript

    table_id = uuid.uuid4()
    display(HTML("""
        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
        <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/datatables.mark.js/2.0.0/datatables.mark.min.css">
        %s

        """ %(df.to_html(table_id=table_id))))

    display(Javascript("""
        function initDataTable(table_id) {
            var data_table = $('#' + table_id);
            data_table.addClass('display');
            data_table.closest('.jp-OutputArea-child').css({"display": "flex", "flex-direction": "row"})
            data_table.DataTable({
                paging: true,
                scrollX: true,
                scrollY: true,
                mark: true
            });
        }
        if (typeof require == 'undefined') {
            function addScript(src) {
                return new Promise((resolve, reject) => {
                    var script = document.createElement('script');
                    script.onload = resolve;
                    script.onerror = reject;
                    script.src = src;
                    document.head.appendChild(script);
                });
            }
            addScript('https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js')
                .then(() => addScript('https://cdn.jsdelivr.net/mark.js/8.6.0/jquery.mark.min.js'))
                .then(() => addScript('https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js'))
                .then(() => addScript('https://cdn.jsdelivr.net/datatables.mark.js/2.0.0/datatables.mark.min.js'))
                .then(() => {
                     $(document).ready( function () {
                        initDataTable("%s");
                    });
                })
        } else {
            require.config({
                paths: {
                    "jquery": 'https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min',
                    "datatables.net": 'https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min',
                    "markjs": "https://cdn.jsdelivr.net/mark.js/8.6.0/jquery.mark.min",
                    "datatables-markjs": "https://cdn.jsdelivr.net/datatables.mark.js/2.0.0/datatables.mark.min"
                }
            });

            require(["datatables-markjs"], function() {
                $(function() {
                    initDataTable("%s");
                });
            });
        }
        """ % (table_id, table_id)
    ))
vincent-grosbois commented 2 years ago

hi @mwouts thanks ! to be honest I didn't expect an anwser / fix that fast :D I'll try to have a look but I'm pretty busy, I should be able to check it this week

mwouts commented 2 years ago

@vincent-grosbois you're welcome.

Also, @qqdaiyu55 thanks for sharing the code snippet above, that is interesting!

I see that we have three distinct sub-issues in this thread

qqdaiyu55 commented 2 years ago

@mwouts Oh yeah, I tested it on JupyterLab/Notebook/Exported HTML, it works well.

mwouts commented 2 years ago

I'll close this issue as we have addressed the rendering of the multi-index columns in the new version itables==0.4.6.

@vincent-grosbois feel free to open a new issue when you see another example for which you'd like to use pandas.to_html.

@qqdaiyu55 I'd like to reuse your example to allow the user to load datatable extensions, do you think you could help me do this at #67 ? Thanks