diff --git a/dynamics.py b/dynamics.py
index f4bfbe5234e6d4633312454b758e697b05861ec5..c131aed3b752c5ed0544fe3fb0d87b2b3cd35e80 100644
--- a/dynamics.py
+++ b/dynamics.py
@@ -24,6 +24,7 @@ THE SOFTWARE.
 
 import abc
 import numpy as np
+import pandas as pd
 from typing import List, Tuple, Union
 
 
@@ -1160,6 +1161,36 @@ class Profile:
         self.values = values
         self.dynamic = dynamic
 
+    @staticmethod
+    def from_csv(
+        path, dynamic: Dynamic
+    ):  # path: [path to a file], type hinting dict[str, Profile]]
+        if isinstance(dynamic, (TrivialDynamic, TreeDynamic)):
+            df = pd.read_csv(path)
+            if len(df) != dynamic.number_of_steps():
+                raise ValueError(
+                    f"The number of rows in the csv file and the number of steps in the dynamic have to be the same!"
+                )
+            return {
+                column: Profile(df[column].values, dynamic) for column in df.columns
+            }
+        elif isinstance(dynamic, AggregatedDynamic):
+            df = pd.read_csv(path, index_col=[0, 1])
+            profiles = {column: dict() for column in df.columns}
+            for period_index in df.index.levels[0]:
+                if (
+                    len(df.loc[period_index])
+                    != dynamic.period_dynamics[period_index].number_of_steps()
+                ):
+                    raise ValueError(
+                        f"The number of rows in the csv file for a period and the number of steps in the period dynamic have to be the same!"
+                    )
+                for column in df.columns:
+                    profiles[column][period_index] = df.loc[period_index][column].values
+            return {column: Profile(profiles[column], dynamic) for column in df.columns}
+        else:
+            raise ValueError(f"Invalid dynamic type {type(dynamic)}!")
+
 
 def test_single_resampling(
     dynamic: TreeDynamic,