Skip to content

Commit

Permalink
Merge branch 'main' into 833-improve-docstrings-for-image-and-imageli…
Browse files Browse the repository at this point in the history
…st-method-convert_to_grayscale
  • Loading branch information
Marsmaennchen221 authored Jun 14, 2024
2 parents 30ef172 + 487854c commit 8aacdaa
Show file tree
Hide file tree
Showing 12 changed files with 410 additions and 5 deletions.
18 changes: 18 additions & 0 deletions src/safeds/data/tabular/containers/_lazy_temporal_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@ def __sizeof__(self) -> int:
# Temporal operations
# ------------------------------------------------------------------------------------------------------------------

def century(self) -> Cell[int]:
return _LazyCell(self._expression.dt.century())

def weekday(self) -> Cell[int]:
return _LazyCell(self._expression.dt.weekday())

def week(self) -> Cell[int]:
return _LazyCell(self._expression.dt.week())

def year(self) -> Cell[int]:
return _LazyCell(self._expression.dt.year())

def month(self) -> Cell[int]:
return _LazyCell(self._expression.dt.month())

def day(self) -> Cell[int]:
return _LazyCell(self._expression.dt.day())

def datetime_to_string(self, format_string: str = "%Y/%m/%d %H:%M:%S") -> Cell[str]:
if not _check_format_string(format_string):
raise ValueError("Invalid format string")
Expand Down
151 changes: 146 additions & 5 deletions src/safeds/data/tabular/containers/_temporal_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@

class TemporalCell(ABC):
"""
A class that contains temporal methods for a column.
Namespace for operations on temporal data.
Parameters
----------
column:
The column to be operated on.
This class cannot be instantiated directly. It can only be accessed using the `dt` attribute of a cell.
Examples
--------
Expand All @@ -31,6 +28,150 @@ class TemporalCell(ABC):
+------------+
"""

@abstractmethod
def century(self) -> Cell[int]:
"""
Get the century of the underlying date(time) data.
Returns
-------
A cell containing the century as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 1)])
>>> column.transform(lambda cell: cell.dt.century())
+---------+
| example |
| --- |
| i32 |
+=========+
| 21 |
+---------+
"""

@abstractmethod
def weekday(self) -> Cell[int]:
"""
Get the weekday of the underlying date(time) data.
Returns
-------
A cell containing the weekday as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 1)])
>>> column.transform(lambda cell: cell.dt.weekday())
+---------+
| example |
| --- |
| i8 |
+=========+
| 6 |
+---------+
"""

@abstractmethod
def week(self) -> Cell[int]:
"""
Get the week of the underlying date(time) data.
Returns
-------
A cell containing the week as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 1)])
>>> column.transform(lambda cell: cell.dt.week())
+---------+
| example |
| --- |
| i8 |
+=========+
| 52 |
+---------+
"""

@abstractmethod
def year(self) -> Cell[int]:
"""
Get the year of the underlying date(time) data.
Returns
-------
A cell containing the year as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 9)])
>>> column.transform(lambda cell: cell.dt.year())
+---------+
| example |
| --- |
| i32 |
+=========+
| 2022 |
+---------+
"""

@abstractmethod
def month(self) -> Cell[int]:
"""
Get the month of the underlying date(time) data.
Returns
-------
A cell containing the month as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 9)])
>>> column.transform(lambda cell: cell.dt.month())
+---------+
| example |
| --- |
| i8 |
+=========+
| 1 |
+---------+
"""

@abstractmethod
def day(self) -> Cell[int]:
"""
Get the day of the underlying date(time) data.
Returns
-------
A cell containing the day as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 9)])
>>> column.transform(lambda cell: cell.dt.day())
+---------+
| example |
| --- |
| i8 |
+=========+
| 9 |
+---------+
"""

@abstractmethod
def datetime_to_string(self, format_string: str = "%Y/%m/%d %H:%M:%S") -> Cell[str]:
"""
Expand Down
2 changes: 2 additions & 0 deletions src/safeds/exceptions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
DatasetMissesFeaturesError,
FeatureDataMismatchError,
InputSizeError,
InvalidFitDataError,
InvalidModelStructureError,
LearningError,
ModelNotFittedError,
Expand Down Expand Up @@ -69,6 +70,7 @@ class OutOfBoundsError(SafeDsError):
"DatasetMissesDataError",
"DatasetMissesFeaturesError",
"FeatureDataMismatchError",
"InvalidFitDataError",
"InputSizeError",
"InvalidModelStructureError",
"LearningError",
Expand Down
7 changes: 7 additions & 0 deletions src/safeds/exceptions/_ml.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ def __init__(self) -> None:
super().__init__("Dataset contains no rows")


class InvalidFitDataError(Exception):
"""Raised when a Neural Network is fitted on invalid data."""

def __init__(self, reason: str) -> None:
super().__init__(f"The given Fit Data is invalid:\n{reason}")


class LearningError(Exception):
"""
Raised when an error occurred while training a model.
Expand Down
19 changes: 19 additions & 0 deletions src/safeds/ml/nn/converters/_input_converter_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from safeds.data.labeled.containers import TabularDataset
from safeds.data.tabular.containers import Column, Table
from safeds.exceptions import InvalidFitDataError

from ._input_converter import InputConversion

Expand Down Expand Up @@ -43,6 +44,24 @@ def _is_fit_data_valid(self, input_data: TabularDataset) -> bool:
self._feature_names = input_data.features.column_names
self._target_name = input_data.target.name
self._first = False

columns_with_missing_values = []
columns_with_non_numerical_data = []

for col in input_data.features.add_columns([input_data.target]).to_columns():
if col.missing_value_count() > 0:
columns_with_missing_values.append(col.name)
if not col.type.is_numeric:
columns_with_non_numerical_data.append(col.name)

reason = ""
if len(columns_with_missing_values) > 0:
reason += f"The following Columns contain missing values: {columns_with_missing_values}\n"
if len(columns_with_non_numerical_data) > 0:
reason += f"The following Columns contain non-numerical data: {columns_with_non_numerical_data}"
if reason != "":
raise InvalidFitDataError(reason)

return (sorted(input_data.features.column_names)).__eq__(sorted(self._feature_names))

def _is_predict_data_valid(self, input_data: Table) -> bool:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(18, datetime.datetime(1800, 1, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(21, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_day(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.century(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_day.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(9, datetime.datetime(2022, 1, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(1, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_day(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.day(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_month.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(3, datetime.datetime(2022, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(1, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_month(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.month(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_week.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(10, datetime.datetime(2023, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(52, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_week(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.week(), expected)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(4, datetime.datetime(2023, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(6, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_weekday(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.weekday(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_year.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(2023, datetime.datetime(2023, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(2022, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_year(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.year(), expected)
Loading

0 comments on commit 8aacdaa

Please sign in to comment.