Repository: KIT-IAI/pyWATTS

Issue:
Variance Extraction Module
**What is your feature request related to?**
* Module request

**Please describe the module/problem**
This module should be able to calculate the variance of a time series

Example:
- Given a window size of 2.
- Input: [1,1,1,2,2,2]
- Expected Output: [0,0,1,0,0]

Discussion:
benHeid: # TODOs
* [ ] Adapt CHANGELOG.md
* [ ] Built API Documentation new so that the new modules are part of the API Documentation. -> Add a link in the rolling modules to rolling base. 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0cfa48f..7aded14 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@
   * Added integration tests to github actions by executing the examples in root directory ([#47](https://github.com/KIT-IAI/pyWATTS/issues/47))
   * Implementation of the profile neural network ([#71](https://github.com/KIT-IAI/pyWATTS/issues/47))
   * Imports from the init files for exception, modules, and wrapper. ([#27](https://github.com/KIT-IAI/pyWATTS/issues/27))
+  * Add rolling_variance, rolling_kurtosis, rolling_skewness. ([#28](https://github.com/KIT-IAI/pyWATTS/issues/28))
+  * Select the kind of groupby in the rolling function by an enum ([#28](https://github.com/KIT-IAI/pyWATTS/issues/28))
 
 ### Changed
 
diff --git a/docs/source/api/pywatts.modules.rst b/docs/source/api/pywatts.modules.rst
index e15762e..9470519 100644
--- a/docs/source/api/pywatts.modules.rst
+++ b/docs/source/api/pywatts.modules.rst
@@ -68,6 +68,22 @@ pywatts.modules.resample module
    :undoc-members:
    :show-inheritance:
 
+pywatts.modules.rolling\_base module
+------------------------------------
+
+.. automodule:: pywatts.modules.rolling_base
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+pywatts.modules.rolling\_kurtosis module
+----------------------------------------
+
+.. automodule:: pywatts.modules.rolling_kurtosis
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
 pywatts.modules.rolling\_mean module
 ------------------------------------
 
@@ -76,6 +92,22 @@ pywatts.modules.rolling\_mean module
    :undoc-members:
    :show-inheritance:
 
+pywatts.modules.rolling\_skewness module
+----------------------------------------
+
+.. automodule:: pywatts.modules.rolling_skewness
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
+pywatts.modules.rolling\_variance module
+----------------------------------------
+
+.. automodule:: pywatts.modules.rolling_variance
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
 pywatts.modules.root\_mean\_squared\_error module
 -------------------------------------------------
 
diff --git a/docs/source/core.rst b/docs/source/core.rst
index fc0a38a..2609759 100644
--- a/docs/source/core.rst
+++ b/docs/source/core.rst
@@ -30,7 +30,7 @@ PyWATTS has the following requirements for modules:
 
 1. The modules have to inherit either from `BaseEstimator`` or BaseTransformer.
 2. The modules have have to implement `fit(...)`, `transform(...)`, `set_params(...)`, and `get_params(...)`.
-  Note that if a module does not need to be fitted, it can inherit from `BaseTransformer` and does not have to implement `fit(...)` by itself.
+   Note that if a module does not need to be fitted, it can inherit from `BaseTransformer` and does not have to implement `fit(...)` by itself.
 3. The first dimension of each data-array in the output time-series has to be a time index.
 
 Steps
diff --git a/pywatts/modules/__init__.py b/pywatts/modules/__init__.py
index 29c91ad..7bac145 100644
--- a/pywatts/modules/__init__.py
+++ b/pywatts/modules/__init__.py
@@ -7,6 +7,10 @@ from pywatts.modules.missing_value_detection import MissingValueDetector
 from pywatts.modules.profile_neural_network import ProfileNeuralNetwork
 from pywatts.modules.resample import Resampler
 from pywatts.modules.rolling_mean import RollingMean
+from pywatts.modules.rolling_kurtosis import RollingKurtosis
+from pywatts.modules.rolling_skewness import RollingSkewness
+from pywatts.modules.rolling_variance import RollingVariance
+from pywatts.modules.rolling_base import RollingGroupBy
 from pywatts.modules.root_mean_squared_error import RmseCalculator
 from pywatts.modules.sample_module import Sampler
 from pywatts.modules.trend_extraction import TrendExtraction
diff --git a/pywatts/modules/rolling_base.py b/pywatts/modules/rolling_base.py
new file mode 100644
index 0000000..a833ab6
--- /dev/null
+++ b/pywatts/modules/rolling_base.py
@@ -0,0 +1,137 @@
+from abc import ABC, abstractmethod
+from enum import IntEnum
+from typing import Dict, Optional
+
+import xarray as xr
+
+from pywatts.core.base import BaseTransformer
+from pywatts.core.exceptions.wrong_parameter_exception import WrongParameterException
+from pywatts.utils._workalendar_utils import _init_calendar
+from pywatts.utils._xarray_time_series_utils import numpy_to_xarray
+
+
+class RollingGroupBy(IntEnum):
+    No = 1
+    WorkdayWeekend = 2
+    WorkdayWeekendAndHoliday = 3
+
+
+class RollingBase(BaseTransformer, ABC):
+    """
+     Module which calculates a rolling mean over a specific window size. Note, currently the smallest resolution of the
+     generated profile is one minute.
+
+     :param name: Name of the new variable
+     :type name: str
+     :param window_size: Window size for which to calculate the mean
+     :type window_size: int
+     :param window_size_unit: Unit of the window size (default: "d" [day])
+     :type window_size_unit: str
+     :param groupy_by: how the entries of the time series should be grouped
+     :type group_by. RollingGroupBy
+     :param continent: If group_by is WorkdayAndHoliday: Continent where the country or region is located
+                          (important for importing calendar module).
+     :type continent: str
+     :param country: If group_by is WorkdayAndHoliday: Country or region to use for holiday calendar (default 'Germany')
+     :type country: str
+     :param closed: If there array is closed left or right
+     :type closed: str
+    """
+
+    def __init__(self, name: str = "RollingMean", window_size=24 * 7, window_size_unit="d",
+                 group_by: RollingGroupBy = RollingGroupBy.No, continent: str = "Europe",
+                 country: str = "Germany", closed="left"):
+
+        super().__init__(name)
+        self.window_size = window_size
+        self.window_size_unit = "d"
+        self.group_by = group_by
+        self.window_size_unit = window_size_unit
+        self.country = country
+        self.continent = continent
+        self.closed = closed
+        self.cal = _init_calendar(self.continent, self.country)
+
+    def get_params(self) -> Dict[str, object]:
+        """
+        Get the parameters of the rolling mean module as dict
+        """
+        return {
+            "window_size": self.window_size,
+            "window_size_unit": self.window_size_unit,
+            "group_by": self.group_by,
+            "country": self.country,
+            "continent": self.continent,
+        }
+
+    def set_params(self, window_size: Optional[int] = None, window_size_unit: Optional[str] = None,
+                   group_by: Optional[RollingGroupBy] = None, continent: Optional[str] = None,
+                   country: Optional[str] = None, closed: Optional[str] = None):
+        """
+        Set parameters of the rolling mean
+        :param window_size: Window size for which to calculate the mean
+        :type window_size: int
+        :param window_size_unit: Unit of the window size (default: "d" [day])
+        :type window_size_unit: str
+        :param groupy_by: how the entries of the time series should be grouped
+        :type group_by. RollingGroupBy
+        :param continent: If group_by is WorkdayAndHoliday: Continent where the country or region is located
+                          (important for importing calendar module).
+        :type continent: str
+        :param country: If group_by is WorkdayAndHoliday: Country or region to use for holiday calendar (default 'Germany')
+        :type country: str
+        :param closed: If there array is closed left or right
+        :type closed: str
+        """
+        if window_size:
+            self.window_size = window_size
+        if window_size_unit:
+            self.window_size_unit = window_size_unit
+        if group_by:
+            self.group_by = group_by
+        if closed:
+            self.closed = closed
+        if continent:
+            self.continent = continent
+        if country:
+            self.country = country
+        self.cal = _init_calendar(self.continent, self.country)
+
+    def transform(self, x: xr.DataArray) -> xr.DataArray:
+        """ Calculates a rolling mean
+
+        :param x: Xarray dataset containing a timeseries specified by the object's 'time_index'
+        :return: The xarray dataset with date features added.
+        """
+
+        df = x.to_dataframe("name")
+
+        if self.group_by == RollingGroupBy.No:
+            rolling = self._get_rolling(df)
+        elif self.group_by == RollingGroupBy.WorkdayWeekend:
+            mask = df.index.map(
+                lambda element: element.minute + 1440 if element.weekday() >= 5 else element.hour).values
+            rolling = df.groupby(mask).rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed,
+                                                    on=df.index).mean().reset_index(0).drop("level_0",
+                                                                                            axis=1).sort_index()
+        elif self.group_by == RollingGroupBy.WorkdayWeekendAndHoliday:
+            mask = df.index.map(lambda element:
+                                element.minute + 1440 if self.cal.is_holiday(element) or element.weekday() >= 5
+                                else element.hour).values
+            rolling = df.groupby(mask).rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed,
+                                                    on=df.index).mean().reset_index(0).drop("level_0",
+                                                                                            axis=1).sort_index()
+        else:
+            raise WrongParameterException(
+                "GroupBy has to be RollingGroupBy.No, RollingGroupBy.WorkdayWeekend, "
+                "RollingGroupBy.WorkdayWeekendAndHoliday.",
+                "During initialisation set either  RollingGroupBy.No, RollingGroupBy.WorkdayWeekend, or "
+                "RollingGroupBy.WorkdayWeekendAndHoliday.",
+                module=self.__class__)
+
+        rolling.fillna(inplace=True, value=0)
+        return numpy_to_xarray(rolling.values.reshape((len(rolling),)), x, self.name)
+
+    @abstractmethod
+    def _get_rolling(self, df):
+        pass
diff --git a/pywatts/modules/rolling_kurtosis.py b/pywatts/modules/rolling_kurtosis.py
new file mode 100644
index 0000000..3d001f7
--- /dev/null
+++ b/pywatts/modules/rolling_kurtosis.py
@@ -0,0 +1,29 @@
+from pywatts.modules.rolling_base import RollingBase
+
+
+class RollingKurtosis(RollingBase):
+    """
+     Module which calculates a rolling kurtosis over a specific window size. Note, currently the smallest resolution of
+     the generated profile is one minute.
+
+     For the documentation of the methods see :class:`pywatts.modules.rolling_base.RollingBase`.
+
+     :param name: Name of the new variable
+     :type name: str
+     :param window_size: Window size for which to calculate the kurtosis
+     :type window_size: int
+     :param window_size_unit: Unit of the window size (default: "d" [day])
+     :type window_size_unit: str
+     :param groupy_by: how the entries of the time series should be grouped
+     :type group_by. RollingGroupBy
+     :param continent: If group_by is WorkdayAndHoliday: Continent where the country or region is located
+                          (important for importing calendar module).
+     :type continent: str
+     :param country: If group_by is WorkdayAndHoliday: Country or region to use for holiday calendar (default 'Germany')
+     :type country: str
+     :param closed: If there array is closed left or right
+     :type closed: str
+    """
+
+    def _get_rolling(self, df):
+        return df.rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed).kurt()
diff --git a/pywatts/modules/rolling_mean.py b/pywatts/modules/rolling_mean.py
index 7fdf719..d5c8d65 100644
--- a/pywatts/modules/rolling_mean.py
+++ b/pywatts/modules/rolling_mean.py
@@ -5,21 +5,18 @@ import xarray as xr
 
 from pywatts.core.base import BaseTransformer
 from pywatts.core.exceptions.wrong_parameter_exception import WrongParameterException
+from pywatts.modules.rolling_base import RollingBase
 from pywatts.utils._workalendar_utils import _init_calendar
 from pywatts.utils._xarray_time_series_utils import numpy_to_xarray
 
 
-class RollingMeanGroupBy(IntEnum):
-    No = 1
-    WorkdayWeekend = 2
-    WorkdayWeekendAndHoliday = 3
-
-
-class RollingMean(BaseTransformer):
+class RollingMean(RollingBase):
     """
      Module which calculates a rolling mean over a specific window size. Note, currently the smallest resolution of the
      generated profile is one minute.
 
+     For the documentation of the methods see :class:`pywatts.modules.rolling_base.RollingBase`.
+
      :param name: Name of the new variable
      :type name: str
      :param window_size: Window size for which to calculate the mean
@@ -27,7 +24,7 @@ class RollingMean(BaseTransformer):
      :param window_size_unit: Unit of the window size (default: "d" [day])
      :type window_size_unit: str
      :param groupy_by: how the entries of the time series should be grouped
-     :type group_by. RollingMeanGroupBy
+     :type group_by. RollingGroupBy
      :param continent: If group_by is WorkdayAndHoliday: Continent where the country or region is located
                           (important for importing calendar module).
      :type continent: str
@@ -37,96 +34,5 @@ class RollingMean(BaseTransformer):
      :type closed: str
     """
 
-    def __init__(self, name: str = "RollingMean", window_size=24 * 7, window_size_unit="d",
-                 group_by: RollingMeanGroupBy = RollingMeanGroupBy.No, continent: str = "Europe",
-                 country: str = "Germany", closed="left"):
-
-        super().__init__(name)
-        self.window_size = window_size
-        self.window_size_unit = "d"
-        self.group_by = group_by
-        self.window_size_unit = window_size_unit
-        self.country = country
-        self.continent = continent
-        self.closed = closed
-        self.cal = _init_calendar(self.continent, self.country)
-
-    def get_params(self) -> Dict[str, object]:
-        """
-        Get the parameters of the rolling mean module as dict
-        """
-        return {
-            "window_size": self.window_size,
-            "window_size_unit": self.window_size_unit,
-            "group_by": self.group_by,
-            "country": self.country,
-            "continent": self.continent,
-        }
-
-    def set_params(self, window_size: Optional[int] = None, window_size_unit: Optional[str] = None,
-                   group_by: Optional[RollingMeanGroupBy] = None, continent: Optional[str] = None,
-                   country: Optional[str] = None, closed: Optional[str] = None):
-        """
-        Set parameters of the rolling mean
-        :param window_size: Window size for which to calculate the mean
-        :type window_size: int
-        :param window_size_unit: Unit of the window size (default: "d" [day])
-        :type window_size_unit: str
-        :param groupy_by: how the entries of the time series should be grouped
-        :type group_by. RollingMeanGroupBy
-        :param continent: If group_by is WorkdayAndHoliday: Continent where the country or region is located
-                          (important for importing calendar module).
-        :type continent: str
-        :param country: If group_by is WorkdayAndHoliday: Country or region to use for holiday calendar (default 'Germany')
-        :type country: str
-        :param closed: If there array is closed left or right
-        :type closed: str
-        """
-        if window_size:
-            self.window_size = window_size
-        if window_size_unit:
-            self.window_size_unit = window_size_unit
-        if group_by:
-            self.group_by = group_by
-        if closed:
-            self.closed = closed
-        if continent:
-            self.continent = continent
-        if country:
-            self.country = country
-        self.cal = _init_calendar(self.continent, self.country)
-
-    def transform(self, x: xr.DataArray) -> xr.DataArray:
-        """ Calculates a rolling mean
-
-        :param x: Xarray dataset containing a timeseries specified by the object's 'time_index'
-        :return: The xarray dataset with date features added.
-        """
-
-        df = x.to_dataframe("name")
-
-        if self.group_by == RollingMeanGroupBy.No:
-            rolling_mean = df.rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed).mean()
-        elif self.group_by == RollingMeanGroupBy.WorkdayWeekend:
-            mask = df.index.map(
-                lambda element: element.minute + 1440 if element.weekday() >= 5 else element.hour).values
-            rolling_mean = df.groupby(mask).rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed,
-                                                    on=df.index).mean().reset_index(0).drop("level_0",
-                                                                                            axis=1).sort_index()
-        elif self.group_by == RollingMeanGroupBy.WorkdayWeekendAndHoliday:
-            mask = df.index.map(lambda element:
-                                element.minute + 1440 if self.cal.is_holiday(element) or element.weekday() >= 5
-                                else element.hour).values
-            rolling_mean = df.groupby(mask).rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed,
-                                                    on=df.index).mean().reset_index(0).drop("level_0",
-                                                                                            axis=1).sort_index()
-        else:
-            raise WrongParameterException(
-                "GroupBy has to be RollingMeanGroupBy.No, RollingMeanGroupBy.WorkdayWeekend, "
-                "RollingMeanGroupBy.WorkdayWeekendAndHoliday.",
-                "During initialisation set either  RollingMeanGroupBy.No, RollingMeanGroupBy.WorkdayWeekend, or "
-                "RollingMeanGroupBy.WorkdayWeekendAndHoliday.",
-                module=RollingMean)
-
-        rolling_mean.fillna(inplace=True, value=0)
-        return numpy_to_xarray(rolling_mean.values.reshape((len(rolling_mean),)), x, self.name)
+    def _get_rolling(self, df):
+        return df.rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed).mean()
diff --git a/pywatts/modules/rolling_skewness.py b/pywatts/modules/rolling_skewness.py
new file mode 100644
index 0000000..26120f7
--- /dev/null
+++ b/pywatts/modules/rolling_skewness.py
@@ -0,0 +1,29 @@
+from pywatts.modules.rolling_base import RollingBase
+
+
+class RollingSkewness(RollingBase):
+    """
+     Module which calculates a rolling skewness over a specific window size. Note, currently the smallest resolution of
+     the generated profile is one minute.
+
+     For the documentation of the methods see  :class:`pywatts.modules.rolling_base.RollingBase`.
+
+     :param name: Name of the new variable
+     :type name: str
+     :param window_size: Window size for which to calculate the skewness
+     :type window_size: int
+     :param window_size_unit: Unit of the window size (default: "d" [day])
+     :type window_size_unit: str
+     :param groupy_by: how the entries of the time series should be grouped
+     :type group_by. RollingGroupBy
+     :param continent: If group_by is WorkdayAndHoliday: Continent where the country or region is located
+                          (important for importing calendar module).
+     :type continent: str
+     :param country: If group_by is WorkdayAndHoliday: Country or region to use for holiday calendar (default 'Germany')
+     :type country: str
+     :param closed: If there array is closed left or right
+     :type closed: str
+    """
+
+    def _get_rolling(self, df):
+        return df.rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed).skew()
diff --git a/pywatts/modules/rolling_variance.py b/pywatts/modules/rolling_variance.py
new file mode 100644
index 0000000..bca4de6
--- /dev/null
+++ b/pywatts/modules/rolling_variance.py
@@ -0,0 +1,29 @@
+from pywatts.modules.rolling_base import RollingBase
+
+
+class RollingVariance(RollingBase):
+    """
+     Module which calculates a rolling variance over a specific window size. Note, currently the smallest resolution of
+     the generated profile is one minute.
+
+     For the documentation of the methods see :class:`pywatts.modules.rolling_base.RollingBase`.
+
+     :param name: Name of the new variable
+     :type name: str
+     :param window_size: Window size for which to calculate the variance
+     :type window_size: int
+     :param window_size_unit: Unit of the window size (default: "d" [day])
+     :type window_size_unit: str
+     :param groupy_by: how the entries of the time series should be grouped
+     :type group_by. RollingGroupBy
+     :param continent: If group_by is WorkdayAndHoliday: Continent where the country or region is located
+                          (important for importing calendar module).
+     :type continent: str
+     :param country: If group_by is WorkdayAndHoliday: Country or region to use for holiday calendar (default 'Germany')
+     :type country: str
+     :param closed: If there array is closed left or right
+     :type closed: str
+    """
+
+    def _get_rolling(self, df):
+        return df.rolling(f"{self.window_size}{self.window_size_unit}", closed=self.closed).var()


Test patch:
diff --git a/tests/unit/modules/test_rolling_kurtosis.py b/tests/unit/modules/test_rolling_kurtosis.py
new file mode 100644
index 0000000..49158a7
--- /dev/null
+++ b/tests/unit/modules/test_rolling_kurtosis.py
@@ -0,0 +1,61 @@
+import unittest
+
+import pandas as pd
+import xarray as xr
+
+from pywatts.modules.rolling_base import RollingGroupBy
+from pywatts.modules.rolling_kurtosis import RollingKurtosis
+
+
+class TestRollingKurtosis(unittest.TestCase):
+    def setUp(self) -> None:
+        self.rolling_kurtosis = RollingKurtosis(window_size=3)
+
+    def tearDown(self) -> None:
+        self.rolling_kurtosis = None
+
+    def test_get_params(self):
+        self.assertEqual(
+            self.rolling_kurtosis.get_params(),
+            {
+                "window_size": 3,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+
+    def test_set_params(self):
+        self.assertEqual(
+            self.rolling_kurtosis.get_params(),
+            {
+                "window_size": 3,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+        self.rolling_kurtosis.set_params(window_size=5)
+        self.assertEqual(
+            self.rolling_kurtosis.get_params(),
+            {
+                "window_size": 5,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+
+    def test_transform_groupbyNo(self):
+        time = pd.date_range('2002-01-01', freq='24H', periods=7)
+
+        da = xr.DataArray([2, 3, 4, 5, 6, 7, 8], dims=["time"], coords={'time': time})
+
+        result = self.rolling_kurtosis.transform(da)
+
+        expected_result = xr.DataArray([0., 0, 0, 0, 0, 0, 0], dims=["time"], coords={'time': time})
+
+        xr.testing.assert_equal(result, expected_result)
diff --git a/tests/unit/modules/test_rolling_mean.py b/tests/unit/modules/test_rolling_mean.py
index a3bf4cd..b1b7521 100644
--- a/tests/unit/modules/test_rolling_mean.py
+++ b/tests/unit/modules/test_rolling_mean.py
@@ -3,7 +3,8 @@ import unittest
 import pandas as pd
 import xarray as xr
 
-from pywatts.modules.rolling_mean import RollingMean, RollingMeanGroupBy
+from pywatts.modules.rolling_base import RollingGroupBy
+from pywatts.modules.rolling_mean import RollingMean
 
 
 class TestRollingMean(unittest.TestCase):
@@ -19,7 +20,7 @@ class TestRollingMean(unittest.TestCase):
             {
                 "window_size": 3,
                 "window_size_unit": "d",
-                "group_by": RollingMeanGroupBy.No,
+                "group_by": RollingGroupBy.No,
                 "country": "Germany",
                 "continent": "Europe"
             }
@@ -31,7 +32,7 @@ class TestRollingMean(unittest.TestCase):
             {
                 "window_size": 3,
                 "window_size_unit": "d",
-                "group_by": RollingMeanGroupBy.No,
+                "group_by": RollingGroupBy.No,
                 "country": "Germany",
                 "continent": "Europe"
             }
@@ -42,7 +43,7 @@ class TestRollingMean(unittest.TestCase):
             {
                 "window_size": 5,
                 "window_size_unit": "d",
-                "group_by": RollingMeanGroupBy.No,
+                "group_by": RollingGroupBy.No,
                 "country": "Germany",
                 "continent": "Europe"
             }
@@ -60,7 +61,7 @@ class TestRollingMean(unittest.TestCase):
         xr.testing.assert_equal(result, expected_result)
 
     def test_transform_groupbyWeekendWeekday(self):
-        self.rolling_mean.set_params(group_by=RollingMeanGroupBy.WorkdayWeekend)
+        self.rolling_mean.set_params(group_by=RollingGroupBy.WorkdayWeekend)
         time = pd.date_range('2002-01-01', freq='24H', periods=7)
 
         ds = xr.DataArray([2, 3, 4, 5, 6, 7, 42], dims=["time"], coords={'time': time})
@@ -73,7 +74,7 @@ class TestRollingMean(unittest.TestCase):
 
     def test_transform_groupbyWeekendWeekdayAndHoliday(self):
         time = pd.date_range('2002-01-01', freq='24H', periods=7)
-        self.rolling_mean.set_params(window_size=4, group_by=RollingMeanGroupBy.WorkdayWeekendAndHoliday)
+        self.rolling_mean.set_params(window_size=4, group_by=RollingGroupBy.WorkdayWeekendAndHoliday)
 
         ds = xr.DataArray([2, 3, 4, 5, 6, 7, 42], dims=["time"], coords={'time': time})
 
diff --git a/tests/unit/modules/test_rolling_skewness.py b/tests/unit/modules/test_rolling_skewness.py
new file mode 100644
index 0000000..8cf924a
--- /dev/null
+++ b/tests/unit/modules/test_rolling_skewness.py
@@ -0,0 +1,61 @@
+import unittest
+
+import pandas as pd
+import xarray as xr
+
+from pywatts.modules.rolling_base import RollingGroupBy
+from pywatts.modules.rolling_skewness import RollingSkewness
+
+
+class TestRollingSkewness(unittest.TestCase):
+    def setUp(self) -> None:
+        self.rolling_skewness = RollingSkewness(window_size=3)
+
+    def tearDown(self) -> None:
+        self.rolling_skewness = None
+
+    def test_get_params(self):
+        self.assertEqual(
+            self.rolling_skewness.get_params(),
+            {
+                "window_size": 3,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+
+    def test_set_params(self):
+        self.assertEqual(
+            self.rolling_skewness.get_params(),
+            {
+                "window_size": 3,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+        self.rolling_skewness.set_params(window_size=5)
+        self.assertEqual(
+            self.rolling_skewness.get_params(),
+            {
+                "window_size": 5,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+
+    def test_transform_groupbyNo(self):
+        time = pd.date_range('2002-01-01', freq='24H', periods=7)
+
+        da = xr.DataArray([2, 2, 2, 5, 8, 8, 8], dims=["time"], coords={'time': time})
+
+        result = self.rolling_skewness.transform(da)
+
+        expected_result = xr.DataArray([0., 0., 0., 0., 1.732051, 0., -1.732051], dims=["time"], coords={'time': time})
+
+        xr.testing.assert_allclose(result, expected_result)
diff --git a/tests/unit/modules/test_rolling_variance.py b/tests/unit/modules/test_rolling_variance.py
new file mode 100644
index 0000000..270f769
--- /dev/null
+++ b/tests/unit/modules/test_rolling_variance.py
@@ -0,0 +1,64 @@
+import unittest
+
+import pandas as pd
+import pytest
+import xarray as xr
+import numpy as np
+
+from pywatts.core.exceptions.wrong_parameter_exception import WrongParameterException
+from pywatts.modules.rolling_base import RollingGroupBy
+from pywatts.modules.rolling_variance import RollingVariance
+
+
+class TestRollingVariance(unittest.TestCase):
+    def setUp(self) -> None:
+        self.rolling_variance = RollingVariance(window_size=3)
+
+    def tearDown(self) -> None:
+        self.rolling_variance = None
+
+    def test_get_params(self):
+        self.assertEqual(
+            self.rolling_variance.get_params(),
+            {
+                "window_size": 3,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+
+    def test_set_params(self):
+        self.assertEqual(
+            self.rolling_variance.get_params(),
+            {
+                "window_size": 3,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+        self.rolling_variance.set_params(window_size=5)
+        self.assertEqual(
+            self.rolling_variance.get_params(),
+            {
+                "window_size": 5,
+                "window_size_unit": "d",
+                "group_by": RollingGroupBy.No,
+                "country": "Germany",
+                "continent": "Europe"
+            }
+        )
+
+    def test_transform_groupbyNo(self):
+        time = pd.date_range('2002-01-01', freq='24H', periods=7)
+
+        da = xr.DataArray([2, 3, 4, 5, 6, 7, 8], dims=["time"], coords={'time': time})
+
+        result = self.rolling_variance.transform(da)
+
+        expected_result = xr.DataArray([0., 0, 0.5, 1., 1., 1., 1.], dims=["time"], coords={'time': time})
+
+        xr.testing.assert_equal(result, expected_result)