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

Interval index and interval_range #7182

Merged
merged 116 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
fd6fb9c
interval dtype and tests
marlenezw Dec 11, 2020
c653ac5
changelog
marlenezw Dec 11, 2020
9549f61
Merge branch 'branch-0.18' of https://github.com/rapidsai/cudf into i…
marlenezw Dec 14, 2020
4a16266
updated closed parameter and tests.
marlenezw Dec 14, 2020
f843042
adding both and neither parameters.
marlenezw Dec 14, 2020
5e61f1a
updates to accomodate interval dataframes.
marlenezw Dec 16, 2020
82ef308
Merge branch 'branch-0.18' of https://github.com/rapidsai/cudf into i…
marlenezw Dec 16, 2020
80d0c40
removing comments and resolving interval_dtype issues.
marlenezw Dec 16, 2020
446e849
Update python/cudf/cudf/core/column/column.py
marlenezw Dec 16, 2020
6b3a9f0
resolving merge conflicts
marlenezw Jan 20, 2021
43ee680
Merge branch 'interval_dtype' of https://github.com/marlenezw/cudf in…
marlenezw Jan 20, 2021
ed2edb1
fixing style issues
marlenezw Jan 20, 2021
11ad3bc
Merge branch 'branch-0.18' of https://github.com/rapidsai/cudf into i…
marlenezw Jan 21, 2021
18a82ae
code for intervalindex and interval range
marlenezw Jan 21, 2021
4255b83
fixing style issues.
marlenezw Jan 21, 2021
8da544b
Merge branch 'branch-0.18' of https://github.com/rapidsai/cudf into i…
marlenezw Jan 21, 2021
bc6b5b3
Merge branch 'branch-0.18' of https://github.com/rapidsai/cudf into i…
marlenezw Jan 22, 2021
1a15565
updates to interval_range
marlenezw Jan 25, 2021
88d3390
fixing merge conflicts.
marlenezw Jan 25, 2021
19135c9
fixing merge conflicts
marlenezw Jan 25, 2021
a6fd058
updates to interval_range after tests.
marlenezw Jan 26, 2021
86e4a20
Merge branch 'branch-0.18' of https://github.com/rapidsai/cudf into i…
marlenezw Jan 26, 2021
48d00a4
Update python/cudf/cudf/core/column/column.py
marlenezw Jan 26, 2021
daeef06
Merge branch 'intervalIndex' of https://github.com/marlenezw/cudf int…
marlenezw Jan 26, 2021
d4ee46a
more tests and changes to range_interval
marlenezw Jan 27, 2021
d88fdb4
added more tests and comments for clarity.
marlenezw Jan 28, 2021
777cdb5
fixing style changes.
marlenezw Jan 28, 2021
a5d192b
fixing merge conflicts
marlenezw Feb 1, 2021
d56ae9a
style changes
marlenezw Feb 1, 2021
e5baeae
updates for branch-0.19
marlenezw Feb 1, 2021
f24f893
adding type annotations.
marlenezw Feb 1, 2021
9914c3a
initial changes
marlenezw Feb 2, 2021
1375e70
changes based on comments.
marlenezw Feb 16, 2021
a6e2cbf
fixing code that caused csv test to fail.
marlenezw Feb 16, 2021
578c54c
style changes.
marlenezw Feb 16, 2021
7d6f40e
fixing merge conflicts.
marlenezw Feb 16, 2021
cca756d
removing changes to changelog.
marlenezw Feb 17, 2021
eb6855b
base changes.
marlenezw Feb 17, 2021
1606292
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Feb 17, 2021
c8e528c
addressing chnages to fame.py and interval.py
marlenezw Feb 17, 2021
0cfe8f9
fixing mypy styling issue.
marlenezw Feb 17, 2021
dba282a
fixing failing index test.
marlenezw Feb 17, 2021
76955cc
Update python/cudf/cudf/core/column/interval.py
marlenezw Feb 18, 2021
4e9ee08
updating from interval dtype changes.
marlenezw Feb 18, 2021
ab788cf
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Feb 18, 2021
7a360d0
adding periods.
marlenezw Feb 18, 2021
444919c
updates to add new param periods and more tests
marlenezw Feb 23, 2021
be4a77a
fixing merge conflicts
marlenezw Feb 23, 2021
4cf229a
fixing mypy style issues.
marlenezw Feb 25, 2021
d16ec1a
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Feb 25, 2021
524709b
fixing mypy failures.
marlenezw Feb 25, 2021
31c9b75
changes to index.py.
marlenezw Feb 25, 2021
1401c11
making code dryer.
marlenezw Feb 25, 2021
9ffa7d2
style changes.
marlenezw Feb 25, 2021
b3f707c
style issue.
marlenezw Feb 25, 2021
45cde0a
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Feb 26, 2021
16d73f6
cleaning up code.
marlenezw Feb 26, 2021
6dc86ec
sytyle.
marlenezw Feb 26, 2021
6764e0b
fixes for mypy.
marlenezw Feb 26, 2021
223f366
cleaning up code.
marlenezw Feb 26, 2021
725847f
changing interval_range to function
marlenezw Mar 2, 2021
2be072d
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 2, 2021
f3245c2
making sure style is ok.
marlenezw Mar 2, 2021
8420555
fixing mypy style issue.
marlenezw Mar 2, 2021
49de389
updates to code.
marlenezw Mar 3, 2021
606bfe1
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 3, 2021
4ea34c3
changes to interval_range and intervalindex
marlenezw Mar 3, 2021
af4ea1d
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 4, 2021
c00ca33
changes to for tests to pass.
marlenezw Mar 5, 2021
819d04a
fixing merge conflicts
marlenezw Mar 5, 2021
6412ab4
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 8, 2021
f6189cf
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 9, 2021
6fd7eb9
cleaning up docs and adding from_breaks method in intervalindex.
marlenezw Mar 9, 2021
92be49f
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 9, 2021
7085def
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 10, 2021
6d062c9
Update python/cudf/cudf/core/index.py
marlenezw Mar 25, 2021
8ec8716
Update python/cudf/cudf/core/index.py
marlenezw Mar 25, 2021
906d82c
Update python/cudf/cudf/core/index.py
marlenezw Mar 25, 2021
37e988b
Update python/cudf/cudf/core/index.py
marlenezw Mar 25, 2021
3a5fd3f
Update python/cudf/cudf/core/index.py
marlenezw Mar 25, 2021
5e38756
Update python/cudf/cudf/core/index.py
marlenezw Mar 25, 2021
4140525
Update python/cudf/cudf/core/index.py
marlenezw Mar 25, 2021
c1cdb93
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 29, 2021
25a9112
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 29, 2021
f38e34b
adding initial updated changes.
marlenezw Mar 29, 2021
dbfcd13
addressing review comments.
marlenezw Mar 30, 2021
121a9be
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 30, 2021
1790abd
updated changes.
marlenezw Mar 31, 2021
a5fa304
Update python/cudf/cudf/core/index.py
marlenezw Mar 31, 2021
191743e
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Mar 31, 2021
8175120
changes for determining bin_edges dtype
marlenezw Mar 31, 2021
edb68ab
removing my example notebook :)
marlenezw Mar 31, 2021
caab20e
style changes
marlenezw Mar 31, 2021
d48e8f0
Merge branch 'intervalIndex' of https://github.com/marlenezw/cudf int…
marlenezw Mar 31, 2021
b66d16c
determining final dtype.
marlenezw Apr 1, 2021
375a00f
slight changes to docs.
marlenezw Apr 1, 2021
a7eddb7
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Apr 1, 2021
a9f6eb0
adding changes to start.
marlenezw Apr 1, 2021
c00b609
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Apr 1, 2021
ecb6245
Merge branch 'branch-0.19' of https://github.com/rapidsai/cudf into i…
marlenezw Apr 1, 2021
4b37080
changing periods to int
marlenezw Apr 1, 2021
00ae319
finding common type to get overall type.
marlenezw Apr 1, 2021
9a306a0
figuring out mypy issues.
marlenezw Apr 1, 2021
33e6699
updates to code and style changes.
marlenezw Apr 1, 2021
31dfa59
Adding support for heterogenous data type spec for start, end, freq
isVoid Apr 2, 2021
f5f1453
Update python/cudf/cudf/core/index.py
marlenezw Apr 2, 2021
479b6df
Update python/cudf/cudf/core/index.py
marlenezw Apr 2, 2021
5c192ff
column empty
marlenezw Apr 2, 2021
d3e2204
Merge branch 'intervalIndex' of https://github.com/marlenezw/cudf int…
marlenezw Apr 2, 2021
dd290ae
change use of as_host_type to as_type
isVoid Apr 2, 2021
ba75420
argument data type check logic fix
isVoid Apr 2, 2021
62fe73d
bug fix, coerce periods to int before
isVoid Apr 2, 2021
f4ff52c
adding empty column.
marlenezw Apr 2, 2021
9044d57
Remove list instantiation for any
isVoid Apr 2, 2021
e715c6c
Merge branch 'intervalIndex' of https://github.com/marlenezw/cudf int…
isVoid Apr 2, 2021
603ba75
Update python/cudf/cudf/core/index.py
marlenezw Apr 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- PR #6814 Implement `cudf::reduce` for `decimal32` and `decimal64` (part 1)
- PR #6929 Add `Index.set_names` api
- PR #6907 Add `replace_null` API with `replace_policy` parameter, `fixed_width` column support
- PR #6984 Add `interval` dtype to cudf
- PR #6885 Share `factorize` implementation with Index and cudf module

- PR #6775 Implement cudf.DateOffset for months
Expand Down
2 changes: 2 additions & 0 deletions python/cudf/cudf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from cudf.core import (
NA,
CategoricalIndex,
interval_range,
IntervalIndex,
DataFrame,
DatetimeIndex,
Float32Index,
Expand Down
2 changes: 2 additions & 0 deletions python/cudf/cudf/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from cudf.core.dataframe import DataFrame, from_pandas, merge
from cudf.core.index import (
CategoricalIndex,
interval_range,
IntervalIndex,
DatetimeIndex,
Float32Index,
Float64Index,
Expand Down
1 change: 1 addition & 0 deletions python/cudf/cudf/core/column/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
from cudf.core.column.string import StringColumn # noqa: F401
from cudf.core.column.struct import StructColumn # noqa: F401
from cudf.core.column.timedelta import TimeDeltaColumn # noqa: F401
from cudf.core.column.interval import IntervalColumn # noqa: F401
59 changes: 51 additions & 8 deletions python/cudf/cudf/core/column/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
is_scalar,
is_string_dtype,
is_struct_dtype,
is_interval_dtype,
min_signed_type,
min_unsigned_type,
np_to_pa_dtype,
Expand Down Expand Up @@ -132,6 +133,10 @@ def to_pandas(self, index=None, nullable=False, **kwargs):
pd_series = pd.Series(pandas_array, copy=False)
elif str(self.dtype) in NUMERIC_TYPES and self.null_count == 0:
pd_series = pd.Series(cupy.asnumpy(self.values), copy=False)
elif is_interval_dtype(self.dtype):
pd_series = pd.Series(
pd.IntervalDtype().__from_arrow__(self.to_arrow())
)
else:
pd_series = self.to_arrow().to_pandas(**kwargs)

Expand Down Expand Up @@ -364,7 +369,6 @@ def from_arrow(cls, array):
"""
if not isinstance(array, (pa.Array, pa.ChunkedArray)):
raise TypeError("array should be PyArrow array or chunked array")

data = pa.table([array], [None])
if isinstance(array.type, pa.DictionaryType):
indices_table = pa.table(
Expand Down Expand Up @@ -400,6 +404,10 @@ def from_arrow(cls, array):
)
elif isinstance(array.type, pa.StructType):
return cudf.core.column.StructColumn.from_arrow(array)
elif isinstance(
array.type, pd.core.arrays._arrow_utils.ArrowIntervalType
):
return cudf.core.column.IntervalColumn.from_arrow(array)

return libcudf.interop.from_arrow(data, data.column_names)._data[
"None"
Expand Down Expand Up @@ -1008,6 +1016,12 @@ def astype(self, dtype, **kwargs):
"Casting list columns not currently supported"
)
return self
elif is_interval_dtype(self.dtype):
if not self.dtype == dtype:
raise NotImplementedError(
"Casting interval columns not currently supported"
)
return self
elif np.issubdtype(dtype, np.datetime64):
return self.as_datetime_column(dtype, **kwargs)
elif np.issubdtype(dtype, np.timedelta64):
Expand Down Expand Up @@ -1480,6 +1494,15 @@ def build_column(
null_count=null_count,
children=children,
)
elif is_interval_dtype(dtype):
return cudf.core.column.IntervalColumn(
data=data,
dtype=dtype,
mask=mask,
size=size,
offset=offset,
null_count=null_count,
)
else:
return cudf.core.column.NumericalColumn(
data=data,
Expand Down Expand Up @@ -1517,14 +1540,12 @@ def build_categorical_column(
ordered : bool
Indicates whether the categories are ordered
"""

codes_dtype = min_unsigned_type(len(categories))
codes = as_column(codes)
if codes.dtype != codes_dtype:
codes = codes.astype(codes_dtype)

dtype = CategoricalDtype(categories=as_column(categories), ordered=ordered)

return build_column(
data=None,
dtype=dtype,
Expand Down Expand Up @@ -1657,6 +1678,8 @@ def as_column(arbitrary, nan_as_null=None, dtype=None, length=None):
return as_column(arbitrary.array)
if is_categorical_dtype(arbitrary):
data = as_column(pa.array(arbitrary, from_pandas=True))
elif is_interval_dtype(arbitrary.dtype):
data = as_column(pa.array(arbitrary, from_pandas=True))
elif arbitrary.dtype == np.bool:
data = as_column(cupy.asarray(arbitrary), dtype=arbitrary.dtype)
elif arbitrary.dtype.kind in ("f"):
Expand Down Expand Up @@ -1776,9 +1799,17 @@ def as_column(arbitrary, nan_as_null=None, dtype=None, length=None):
data=buffer, mask=mask, dtype=arbitrary.dtype
)
elif arb_dtype.kind in ("O", "U"):
data = as_column(
pa.Array.from_pandas(arbitrary), dtype=arbitrary.dtype
)
if isinstance(arbitrary[0], pd._libs.interval.Interval):
# changing from pd array to series,possible arrow bug
interval_series = pd.Series(arbitrary)
data = as_column(
pa.Array.from_pandas(interval_series),
dtype=arbitrary.dtype,
)
else:
data = as_column(
pa.Array.from_pandas(arbitrary), dtype=arbitrary.dtype
)
# There is no cast operation available for pa.Array from int to
# str, Hence instead of handling in pa.Array block, we
# will have to type-cast here.
Expand Down Expand Up @@ -1806,7 +1837,16 @@ def as_column(arbitrary, nan_as_null=None, dtype=None, length=None):
if arb_dtype != arbitrary.dtype.numpy_dtype:
arbitrary = arbitrary.astype(arb_dtype)
if arb_dtype.kind in ("O", "U"):
data = as_column(pa.Array.from_pandas(arbitrary), dtype=arb_dtype)
if isinstance(arbitrary[0], pd._libs.interval.Interval):
# changing from pd array to series,possible arrow bug
interval_series = pd.Series(arbitrary)
data = as_column(
pa.Array.from_pandas(interval_series), dtype=arb_dtype
)
else:
data = as_column(
pa.Array.from_pandas(arbitrary), dtype=arb_dtype
)
else:
data = as_column(
pa.array(
Expand Down Expand Up @@ -1854,7 +1894,7 @@ def as_column(arbitrary, nan_as_null=None, dtype=None, length=None):
)
return as_column(data, nan_as_null=nan_as_null)
dtype = pd.api.types.pandas_dtype(dtype)
if is_categorical_dtype(dtype):
if is_categorical_dtype(dtype) or is_interval_dtype(dtype):
raise TypeError
else:
np_type = np.dtype(dtype).type
Expand All @@ -1880,6 +1920,9 @@ def as_column(arbitrary, nan_as_null=None, dtype=None, length=None):
elif np_type == np.str_:
sr = pd.Series(arbitrary, dtype="str")
data = as_column(sr, nan_as_null=nan_as_null)
elif is_interval_dtype(dtype):
sr = pd.Series(arbitrary, dtype="interval")
data = as_column(sr, nan_as_null=nan_as_null)
else:
native_dtype = dtype
if dtype is None and pd.api.types.infer_dtype(
Expand Down
58 changes: 58 additions & 0 deletions python/cudf/cudf/core/column/interval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import pyarrow as pa
import cudf
from cudf.core.column import StructColumn


class IntervalColumn(StructColumn):
def __init__(
self,
dtype,
mask=None,
size=None,
offset=0,
null_count=None,
children=(),
closed="right",
):

super().__init__(
data=None,
dtype=dtype,
mask=mask,
size=size,
offset=offset,
null_count=null_count,
children=children,
)
self.closed = closed

@classmethod
def from_arrow(self, data):
new_col = super().from_arrow(data.storage)
size = len(data)
dtype = cudf.core.dtypes.IntervalDtype.from_arrow(data.type)
mask = data.buffers()[0]
if mask is not None:
mask = cudf.utils.utils.pa_mask_buffer_to_mask(mask, len(data))

offset = data.offset
null_count = data.null_count
children = new_col.children
closed = dtype.closed

return IntervalColumn(
size=size,
dtype=dtype,
mask=mask,
offset=offset,
null_count=null_count,
children=children,
closed=closed,
)

def to_arrow(self):
typ = self.dtype.to_arrow()
return pa.ExtensionArray.from_storage(typ, super().to_arrow())

def copy(self, deep=True):
return super().copy(deep=deep).as_interval_column(self.closed)
15 changes: 15 additions & 0 deletions python/cudf/cudf/core/column/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ def copy(self, deep=True):
result = result._rename_fields(self.dtype.fields.keys())
return result

def as_interval_column(self, closed="right"):
from cudf.core.column import IntervalColumn

return IntervalColumn(
size=self.size,
dtype=cudf.core.dtypes.IntervalDtype(
self.dtype.fields["left"], closed
),
mask=self.mask,
offset=self.offset,
null_count=self.null_count,
children=self.children,
closed=closed,
)

def _rename_fields(self, names):
"""
Return a StructColumn with the same field values as this StructColumn,
Expand Down
5 changes: 4 additions & 1 deletion python/cudf/cudf/core/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,11 +418,14 @@ def _init_from_list_like(self, data, index=None, columns=None):
index = as_index(index)

self._index = as_index(index)

# list-of-dicts case
if len(data) > 0 and isinstance(data[0], dict):
data = DataFrame.from_pandas(pd.DataFrame(data))
self._data = data._data
# interval in a list
elif len(data) > 0 and isinstance(data[0], pd._libs.interval.Interval):
data = DataFrame.from_pandas(pd.DataFrame(data))
self._data = data._data
else:
data = list(itertools.zip_longest(*data))

Expand Down
29 changes: 28 additions & 1 deletion python/cudf/cudf/core/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pandas as pd
import pyarrow as pa
from pandas.api.extensions import ExtensionDtype
from pandas.core.arrays._arrow_utils import ArrowIntervalType

import cudf

Expand Down Expand Up @@ -214,7 +215,7 @@ def __eq__(self, other):
return self._typ.equals(other._typ)

def __repr__(self):
return f"StructDtype({self.fields})"
return f"{type(self).__name__}({self.fields})"

def __hash__(self):
return hash(self._typ)
Expand Down Expand Up @@ -248,5 +249,31 @@ def to_arrow(self):
def from_arrow(cls, typ):
return cls(typ.precision, typ.scale)


class IntervalDtype(StructDtype):
name = "interval"

def __init__(self, subtype, closed="right"):
"""
subtype: str, np.dtype
The dtype of the Interval bounds.
"""
super().__init__(fields={"left": subtype, "right": subtype})
self.closed = closed

@property
def subtype(self):
return self.fields["left"]

@classmethod
def from_arrow(cls, typ):
return IntervalDtype(typ.subtype.to_pandas_dtype(), typ.closed)

def to_arrow(self):

return ArrowIntervalType(
pa.from_numpy_dtype(self.subtype), self.closed
)

def __hash__(self):
return hash(self._typ)
8 changes: 8 additions & 0 deletions python/cudf/cudf/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2384,9 +2384,17 @@ def _copy_struct_names(self, other, include_index=True):

return self

def _copy_interval_data(self, other, include_index=True):
for name, col, other_col in zip(
self._data.keys(), self._data.values(), other._data.values()
):
if isinstance(other_col, cudf.core.column.IntervalColumn):
self._data[name] = col.as_interval_column()

def _postprocess_columns(self, other, include_index=True):
self._copy_categories(other, include_index=include_index)
self._copy_struct_names(other, include_index=include_index)
self._copy_interval_data(other, include_index=include_index)

def _unaryop(self, op):
data_columns = (col.unary_operator(op) for col in self._columns)
Expand Down
Loading