Skip to content

Commit

Permalink
OrangeDataFrame: Replace patched constructor hack with a real constru…
Browse files Browse the repository at this point in the history
…ctor
  • Loading branch information
janezd committed Sep 28, 2024
1 parent 696c942 commit 98c48e1
Showing 1 changed file with 20 additions and 16 deletions.
36 changes: 20 additions & 16 deletions Orange/data/pandas_compat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Pandas DataFrame↔Table conversion helpers"""
from unittest.mock import patch
import pandas.core.arrays.sparse.accessor
from functools import partial

import numpy as np
from scipy import sparse as sp
Expand All @@ -22,6 +23,17 @@
__all__ = ['table_from_frame', 'table_to_frame']


# Patch a bug in pandas SparseFrameAccessor.to_dense
# As of pandas=3.0.0.dev0+1524.g23c497bb2f, to_dense ignores _constructor
# and alwats returns DataFrame.
def to_dense(self):
data = {k: v.array.to_dense() for k, v in self._parent.items()}
constr = self._parent._constructor
return constr(data, index=self._parent.index, columns=self._parent.columns)

pandas.core.arrays.sparse.accessor.SparseFrameAccessor.to_dense = to_dense


class OrangeDataFrame(pd.DataFrame):
_metadata = ["orange_variables", "orange_weights",
"orange_attributes", "orange_role"]
Expand Down Expand Up @@ -74,8 +86,6 @@ def __init__(self, *args, **kwargs):
data = dict(enumerate(sparrays))
super().__init__(data, index=index, **kwargs)
self.columns = columns
# a hack to keep Orange df _metadata in sparse->dense conversion
self.sparse.to_dense = self.__patch_constructor(self.sparse.to_dense)
else:
copy = kwargs.pop("copy", False)
super().__init__(
Expand All @@ -88,21 +98,15 @@ def __init__(self, *args, **kwargs):
if table.W.size > 0 else {})
self.orange_attributes = table.attributes

def __patch_constructor(self, method):
def new_method(*args, **kwargs):
with patch(
'pandas.DataFrame',
OrangeDataFrame
):
df = method(*args, **kwargs)
df.__finalize__(self)
return df

return new_method

@property
def _constructor(self):
return OrangeDataFrame
return partial(self.from_existing, self)

@staticmethod
def from_existing(existing, *args, **kwargs):
self = type(existing)(*args, **kwargs)
self.__finalize__(existing)
return self

def to_orange_table(self):
return table_from_frame(self)
Expand Down

0 comments on commit 98c48e1

Please sign in to comment.