Skip to content

[Bug]: Issue when rendering DataGrid with numeric column name #2115

@shawnboltz

Description

@shawnboltz

Component

Reactive Programming

Severity

P3 - Low (minor inconvenience)

Shiny Version

1.5.1

Python Version

3.12.12

Minimal Reproducible Example

from shiny.express import render

@render.data_frame
def table():
    df = pd.DataFrame([["a", 1], ["b", 2], ["c", 3], ["d", 4]], columns=[0, 1])
    return render.DataGrid(df)

Behavior

Current behavior:
I attempted to render a pandas DataFrame that has numeric column names and it failed with an obscure error.

Expected behavior:
The DataFrame should have been rendered without issue with the numeric column names.

Proposed solution/context:
This is easily worked around by naming the columns something rather than letting them just be numeric (to be fair, this was an error on my part).

However, it took some deep digging to identify the root cause. In shiny.render._data_frame_utils._tbl_data.serialize_frame, the following code appears:

def serialize_frame(into_data: IntoDataFrame) -> FrameJson:

    data = as_data_frame(into_data)

    type_hints = [serialize_dtype(data[col_name]) for col_name in data.columns]

The first line converts the pandas DataFrame into a narwhals DataFrame and the second accesses each column by name. In the case of a numeric column name, i.e. your column name is 0, then data[0] returns the first row of the DataFrame and it returns it as a DataFrame rather than a Series, causing the confusing error.

A more robust way of accessing a column in a narwhals DataFrame would be to use the .get_column method, which gets around this ambiguity: type_hints = [serialize_dtype(data.get_column(col_name)) for col_name in data.columns]

Error Messages (if any)

Traceback (most recent call last):
  File "{Python_env}\shiny\session\_session.py", line 1836, in output_obs
    value = await renderer.render()
            ^^^^^^^^^^^^^^^^^^^^^^^
  File "{Python_env}\shiny\render\_data_frame.py", line 1005, in render
    payload = value.to_payload()
  File "{Python_env}\shiny\render\_data_frame_utils\_datagridtable.py", line 168, in to_payload
    **serialize_frame(self.data),
      ~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "{Python_env}\shiny\render\_data_frame_utils\_tbl_data.py", line 240, in serialize_frame
    type_hints = [serialize_dtype(data[col_name]) for col_name in data.columns]
                  ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "{Python_env}\shiny\render\_data_frame_utils\_tbl_data.py", line 186, in serialize_dtype
    dtype: DType = col.dtype
                   ^^^^^^^^^
AttributeError: 'DataFrame' object has no attribute 'dtype'

Environment

OS: Windows 11
Browser: Firefox
Dependencies:
shiny 1.5.0
narwhals 2.10.0
pandas 2.3.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions