ydataai / ydata-profiling

1 Line of code data quality profiling & exploratory data analysis for Pandas and Spark DataFrames.
https://docs.profiling.ydata.ai
MIT License
12.45k stars 1.68k forks source link

TraitError: n_rows and n_columns must be positive integer #853

Open jijasmx opened 3 years ago

jijasmx commented 3 years ago

Missing functionality

1 profile.to_widgets() ~\anaconda3\lib\site-packages\pandas_profiling\profile_report.py in to_widgets(self) 412 from IPython.core.display import display 413 --> 414 display(self.widgets) 415 416 def _repr_html_(self) -> None: ~\anaconda3\lib\site-packages\pandas_profiling\profile_report.py in widgets(self) 195 def widgets(self) -> Renderable: 196 if self._widgets is None: --> 197 self._widgets = self._render_widgets() 198 return self._widgets 199 ~\anaconda3\lib\site-packages\pandas_profiling\profile_report.py in _render_widgets(self) 321 leave=False, 322 ) as pbar: --> 323 widgets = WidgetReport(copy.deepcopy(report)).render() 324 pbar.update() 325 return widgets ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\root.py in render(self, **kwargs) 7 def render(self, **kwargs) -> widgets.VBox: 8 return widgets.VBox( ----> 9 [self.content["body"].render(), self.content["footer"].render()] 10 ) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in render(self) 104 widget = get_named_list(self.content["items"]) 105 elif self.sequence_type in ["tabs", "sections", "select"]: --> 106 widget = get_tabs(self.content["items"]) 107 elif self.sequence_type == "accordion": 108 widget = get_accordion(self.content["items"]) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in get_tabs(items) 18 titles = [] 19 for item in items: ---> 20 children.append(item.render()) 21 titles.append(get_name(item)) 22 ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in render(self) 106 widget = get_tabs(self.content["items"]) 107 elif self.sequence_type == "accordion": --> 108 widget = get_accordion(self.content["items"]) 109 elif self.sequence_type == "grid": 110 widget = get_row(self.content["items"]) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in get_accordion(items) 87 titles = [] 88 for item in items: ---> 89 children.append(item.render()) 90 titles.append(get_name(item)) 91 ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\variable.py in render(self) 8 items = [self.content["top"].render()] 9 if self.content["bottom"] is not None: ---> 10 items.append(self.content["bottom"].render()) 11 12 return widgets.VBox(items) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\collapse.py in render(self) 12 13 toggle = self.content["button"].render() ---> 14 item = self.content["item"].render() 15 16 if collapse == "correlation": ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in render(self) 104 widget = get_named_list(self.content["items"]) 105 elif self.sequence_type in ["tabs", "sections", "select"]: --> 106 widget = get_tabs(self.content["items"]) 107 elif self.sequence_type == "accordion": 108 widget = get_accordion(self.content["items"]) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in get_tabs(items) 18 titles = [] 19 for item in items: ---> 20 children.append(item.render()) 21 titles.append(get_name(item)) 22 ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in render(self) 108 widget = get_accordion(self.content["items"]) 109 elif self.sequence_type == "grid": --> 110 widget = get_row(self.content["items"]) 111 elif self.sequence_type == "batch_grid": 112 widget = get_batch_grid( ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in get_row(items) 55 raise ValueError("Layout undefined for this number of columns") 56 ---> 57 return widgets.GridBox([item.render() for item in items], layout=layout) 58 59 ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in (.0) 55 raise ValueError("Layout undefined for this number of columns") 56 ---> 57 return widgets.GridBox([item.render() for item in items], layout=layout) 58 59 ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in render(self) 104 widget = get_named_list(self.content["items"]) 105 elif self.sequence_type in ["tabs", "sections", "select"]: --> 106 widget = get_tabs(self.content["items"]) 107 elif self.sequence_type == "accordion": 108 widget = get_accordion(self.content["items"]) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in get_tabs(items) 18 titles = [] 19 for item in items: ---> 20 children.append(item.render()) 21 titles.append(get_name(item)) 22 ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in render(self) 102 widget = get_list(self.content["items"]) 103 elif self.sequence_type == "named_list": --> 104 widget = get_named_list(self.content["items"]) 105 elif self.sequence_type in ["tabs", "sections", "select"]: 106 widget = get_tabs(self.content["items"]) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in get_named_list(items) 34 def get_named_list(items: List[Renderable]) -> widgets.VBox: 35 return widgets.VBox( ---> 36 [ 37 widgets.VBox( 38 [widgets.HTML(f"{get_name(item)}"), item.render()] ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\container.py in (.0) 36 [ 37 widgets.VBox( ---> 38 [widgets.HTML(f"{get_name(item)}"), item.render()] 39 ) 40 for item in items ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\frequency_table.py in render(self) 54 ) 55 ---> 56 return get_table(items) ~\anaconda3\lib\site-packages\pandas_profiling\report\presentation\flavours\widget\frequency_table.py in get_table(items) 9 items: List[Tuple[widgets.Label, widgets.FloatProgress, widgets.Label]] 10 ) -> VBox: ---> 11 table = GridspecLayout(len(items), 3) 12 for row_id, (label, progress, count) in enumerate(items): 13 table[row_id, 0] = label ~\anaconda3\lib\site-packages\ipywidgets\widgets\widget_templates.py in __init__(self, n_rows, n_columns, **kwargs) 280 def __init__(self, n_rows=None, n_columns=None, **kwargs): 281 super(GridspecLayout, self).__init__(**kwargs) --> 282 self.n_rows = n_rows 283 self.n_columns = n_columns 284 self._grid_template_areas = [['.'] * self.n_columns for i in range(self.n_rows)] ~\anaconda3\lib\site-packages\traitlets\traitlets.py in __set__(self, obj, value) 602 raise TraitError('The "%s" trait is read-only.' % self.name) 603 else: --> 604 self.set(obj, value) 605 606 def _validate(self, obj, value): ~\anaconda3\lib\site-packages\traitlets\traitlets.py in set(self, obj, value) 576 577 def set(self, obj, value): --> 578 new_value = self._validate(obj, value) 579 try: 580 old_value = obj._trait_values[self.name] ~\anaconda3\lib\site-packages\traitlets\traitlets.py in _validate(self, obj, value) 610 value = self.validate(obj, value) 611 if obj._cross_validation_lock is False: --> 612 value = self._cross_validate(obj, value) 613 return value 614 ~\anaconda3\lib\site-packages\traitlets\traitlets.py in _cross_validate(self, obj, value) 616 if self.name in obj._trait_validators: 617 proposal = Bunch({'trait': self, 'value': value, 'owner': obj}) --> 618 value = obj._trait_validators[self.name](obj, proposal) 619 elif hasattr(obj, '_%s_validate' % self.name): 620 meth_name = '_%s_validate' % self.name ~\anaconda3\lib\site-packages\traitlets\traitlets.py in __call__(self, *args, **kwargs) 973 """Pass `*args` and `**kwargs` to the handler's function if it exists.""" 974 if hasattr(self, 'func'): --> 975 return self.func(*args, **kwargs) 976 else: 977 return self._init_call(*args, **kwargs) ~\anaconda3\lib\site-packages\ipywidgets\widgets\widget_templates.py in _validate_integer(self, proposal) 293 if proposal['value'] > 0: 294 return proposal['value'] --> 295 raise TraitError('n_rows and n_columns must be positive integer') 296 297 def _get_indices_from_slice(self, row, column): TraitError: n_rows and n_columns must be positive integer
kaharlichenko commented 2 years ago

I'm getting the same stacktrace. Is there anything we can do to help pinpoint the problem?

sbrugman commented 2 years ago

@kaharlichenko thanks for helping to pinpoint the issue. In the original report the python/conda/pip versions are lacking, making it nearly impossible to debug. Especially the ipywidgets version. Does updating help?

kaharlichenko commented 2 years ago

Here's the minimal piece of code that reproduces the bug for me:

import pandas as pd
from pandas_profiling import ProfileReport

df = pd.DataFrame(
    data=[
        ["foo", 1],
        ["bar", 2],
    ],
    columns=["a", "b"],
)

profile = ProfileReport(df, title="Bug Report")
profile.to_widgets()

I'm running Python 3.8.10. The package versions are below.

Package Versions | package | version | |-----------------------|-----------| | argon2-cffi | 21.1.0 | | attrs | 21.2.0 | | backcall | 0.2.0 | | bleach | 4.1.0 | | certifi | 2021.10.8 | | cffi | 1.15.0 | | charset-normalizer | 2.0.7 | | cycler | 0.11.0 | | debugpy | 1.5.1 | | decorator | 5.1.0 | | defusedxml | 0.7.1 | | entrypoints | 0.3 | | htmlmin | 0.1.12 | | idna | 3.3 | | imagehash | 4.2.1 | | importlib-resources | 5.4.0 | | ipykernel | 6.5.0 | | ipython | 7.29.0 | | ipython-genutils | 0.2.0 | | ipywidgets | 7.6.5 | | jedi | 0.18.0 | | jinja2 | 3.0.3 | | joblib | 1.0.1 | | jsonschema | 4.2.1 | | jupyter-client | 7.0.6 | | jupyter-core | 4.9.1 | | jupyterlab-pygments | 0.1.2 | | jupyterlab-widgets | 1.0.2 | | kiwisolver | 1.3.2 | | markupsafe | 2.0.1 | | matplotlib | 3.4.3 | | matplotlib-inline | 0.1.3 | | missingno | 0.5.0 | | mistune | 0.8.4 | | multimethod | 1.6 | | nbclient | 0.5.5 | | nbconvert | 6.2.0 | | nbformat | 5.1.3 | | nest-asyncio | 1.5.1 | | networkx | 2.6.3 | | notebook | 6.4.5 | | numpy | 1.21.1 | | packaging | 21.0 | | pandas | 1.3.4 | | pandas-profiling | 3.1.0 | | pandocfilters | 1.5.0 | | parso | 0.8.2 | | pexpect | 4.8.0 | | phik | 0.12.0 | | pickleshare | 0.7.5 | | pillow | 8.4.0 | | prometheus-client | 0.12.0 | | prompt-toolkit | 3.0.22 | | ptyprocess | 0.7.0 | | pycparser | 2.21 | | pydantic | 1.8.2 | | pygments | 2.10.0 | | pyparsing | 3.0.5 | | pyrsistent | 0.18.0 | | python-dateutil | 2.8.2 | | pytz | 2021.3 | | pywavelets | 1.2.0 | | pyyaml | 6.0 | | pyzmq | 22.3.0 | | requests | 2.26.0 | | scipy | 1.6.1 | | seaborn | 0.11.2 | | send2trash | 1.8.0 | | six | 1.16.0 | | tangled-up-in-unicode | 0.1.0 | | terminado | 0.12.1 | | testpath | 0.5.0 | | tornado | 6.1 | | tqdm | 4.62.3 | | traitlets | 5.1.1 | | typing-extensions | 3.10.0.2 | | urllib3 | 1.26.7 | | visions | 0.7.4 | | wcwidth | 0.2.5 | | webencodings | 0.5.1 | | widgetsnbextension | 3.5.2 | | zipp | 3.6.0 |

The project dependencies and the lock files: poetry.lock pyproject.toml

I hope it helps.

ierezell commented 2 years ago

I also have the same problem and I can reproduce with the dummy example above.

Installed with poetry :

name         : ipywidgets
version      : 7.6.5

name         : pandas-profiling
version      : 3.1.0

Thanks in advance for any help

sbrugman commented 2 years ago

Could you try if the develop branch solves this issue (pip install git+https://github.com/pandas-profiling/pandas-profiling.git@develop - which is v3.1.1)?

kaharlichenko commented 2 years ago

I can confirm that I can't reproduce the bug with the version installed from the develop branch. I tried both the minimal code above and the real profiling project that I have. Thank you for the fix.

AdamXCA commented 2 years ago

I have the same problem as this, and I fixed it by the steps below.

uninstall pandas profiling update Anaconda update Notebook !pip install https://github.com/pandas-profiling/pandas-profiling/archive/refs/tags/v3.0.0.zip

let me know if it works for you