diff --git a/prwlr/core.py b/prwlr/core.py
index f512fc7..eee71c2 100644
--- a/prwlr/core.py
+++ b/prwlr/core.py
@@ -1,3 +1,4 @@
+import gc
 import pandas as _pd
 import numpy as _np
 from . import databases as _databases
@@ -221,6 +222,64 @@ def save_profiles(
         },
     ).to_csv(filename, **kwargs)
 
+def save_network(
+    dataframe,
+    filename,
+    profile_query_column=Columns.PROF_Q,
+    profile_array_column=Columns.PROF_A,
+    profile_reference_column_suffix=Columns.REF,
+    profile_query_column_suffix=Columns.QRY,
+    str_sep='|',
+    **kwargs
+):
+    """
+    Saves pandas.DataFrame with prwlr.profiles.Profile to CSV.
+
+    Parameters
+    -------
+    filename: str, path
+        Filename of the CSV.
+    profile_query_column: str, default prwlr.core.Columns.PROF_Q
+        Column name of the query profile. The default value is taken from the
+        module-wide settings.
+    profile_array_column: str, default prwlr.core.Columns.PROF_A
+        Column name of the array profile. The default value is taken from the
+        module-wide settings.
+    profile_reference_column_suffix: str, default prwlr.core.Columns.REF
+        Column name suffix  of the profile's reference
+        (see prwlr.profiles.Profile).
+    profile_query_column_suffix: str, default prwlr.core.Columns.QRY
+        Column name suffix  of the profile's query
+        (see prwlr.profiles.Profile).
+    str_sep: str, default '|'
+        The internal separator for the profile's reference/query.
+
+    Returns
+    -------
+        pandas.DataFrame
+    """
+    qry_ref_col = '{}_{}'.format(profile_query_column, profile_reference_column_suffix)
+    qry_qry_col = '{}_{}'.format(profile_query_column, profile_query_column_suffix)
+    arr_ref_col = '{}_{}'.format(profile_array_column, profile_reference_column_suffix)
+    arr_qry_col = '{}_{}'.format(profile_array_column, profile_query_column_suffix)
+    df = dataframe.copy()
+    df[qry_ref_col] = df[profile_query_column].apply(
+        lambda x: x.reference,
+    ).str.join(str_sep)
+    df[qry_qry_col] = df[profile_query_column].apply(
+        lambda x: x.query,
+    ).str.join(str_sep)
+    df[arr_ref_col] = df[profile_array_column].apply(
+        lambda x: x.reference,
+    ).str.join(str_sep)
+    df[arr_qry_col] = df[profile_array_column].apply(
+        lambda x: x.query,
+    ).str.join(str_sep)
+    df.drop(
+        columns=[profile_query_column, profile_array_column],
+    ).to_csv(filename, **kwargs)
+    del df; gc.collect()
+
 def merge_sga_profiles(
     sga,
     profiles
@@ -294,8 +353,3 @@ def calculate_pss(
             axis=1,
         )
     return network
-
-def pss(ar1, ar2):
-    return sum(a == b for a, b in zip(ar1, ar2))
-
-pss_vect = _np.vectorize(pss)

prwlr.save_network
The highest-level convenience method prwlr.save_network should be implemented in prwlr.core so that whole network can be saved without losing prwlr.profiles.Profile objects.
diff --git a/test_data/CoreTests/test_network.csv b/test_data/CoreTests/ref_network.csv
similarity index 100%
rename from test_data/CoreTests/test_network.csv
rename to test_data/CoreTests/ref_network.csv
diff --git a/test_data/CoreTests/test_profiles.csv b/test_data/CoreTests/ref_profiles.csv
similarity index 100%
rename from test_data/CoreTests/test_profiles.csv
rename to test_data/CoreTests/ref_profiles.csv
diff --git a/tests/tests.py b/tests/tests.py
index 4c91dd5..88cc936 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -648,9 +648,10 @@ class CoreTests(unittest.TestCase):
         self.ref_query_1 = list('acdfhiklostuz')
         self.ref_reference_2 = list('acefghijklmnprstuwxy')
         self.ref_query_2 = list('abdfhiklostuz')
-        self.test_profiles_filename = 'test_data/CoreTests/test_profiles.csv'
-        self.test_network_filename = 'test_data/CoreTests/test_network.csv'
+        self.ref_profiles_filename = 'test_data/CoreTests/ref_profiles.csv'
+        self.ref_network_filename = 'test_data/CoreTests/ref_network.csv'
         self.test_saved_profiles_filename = 'test_data/CoreTests/test_save_profiles.csv'
+        self.test_saved_network_filename = 'test_data/CoreTests/test_save_network.csv'
 
         self.ref_profile_1, self.ref_profile_2 = (
             prwlr.profiles.Profile(
@@ -683,6 +684,8 @@ class CoreTests(unittest.TestCase):
         """
         if os.path.exists(self.test_saved_profiles_filename):
             os.remove(self.test_saved_profiles_filename)
+        if os.path.exists(self.test_saved_network_filename):
+            os.remove(self.test_saved_network_filename)
 
     def test_read_profiles(self):
         """
@@ -694,7 +697,7 @@ class CoreTests(unittest.TestCase):
         pd.testing.assert_series_equal(
             self.ref_profiles_srs,
             prwlr.core.read_profiles(
-                self.test_profiles_filename,
+                self.ref_profiles_filename,
                 index_col=[0],
             ),
         )
@@ -709,12 +712,32 @@ class CoreTests(unittest.TestCase):
         pd.testing.assert_frame_equal(
             self.ref_network_df,
             prwlr.core.read_network(
-                self.test_network_filename,
+                self.ref_network_filename,
                 index_col=[0],
             ),
             check_like=True,
         )
 
+    def test_save_network(self):
+        """
+        Tests if prwlr.core.save_network saves network suitable for
+        prwlr.core.read_network.
+        """
+        import prwlr.core
+
+        prwlr.core.save_network(
+            self.ref_network_df,
+            self.test_saved_network_filename,
+        )
+        pd.testing.assert_frame_equal(
+            self.ref_network_df,
+            prwlr.core.read_network(
+                self.test_saved_network_filename,
+                index_col=[0],
+                ),
+            check_like=True,
+        )
+
     def test_save_profiles(self):
         """
         Tests if prwlr.core.save_profiles writes CSV file with correct values.

pip install -e .
parse_log_pytest
requirements.txt
nose pytest
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
cycler==0.11.0
decorator==4.4.2
dill==0.3.4
idna==3.10
importlib-metadata==4.8.3
importlib-resources==5.4.0
iniconfig==1.1.1
kiwisolver==1.3.1
matplotlib==3.3.4
multiprocess==0.70.12.2
networkx==2.5.1
nose==1.3.7
numpy==1.19.5
packaging==21.3
pandas==0.23.0
pathos==0.2.8
Pillow==8.4.0
pluggy==1.0.0
pox==0.3.0
ppft==1.6.6.4
-e git+https://github.com/dizak/prwlr.git@1a18b4a13f5eedeaa44610db8f0e98611d933601#egg=prwlr
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.27.1
scipy==1.5.4
six==1.17.0
tomli==1.2.3
tqdm==4.64.1
typing_extensions==4.1.1
urllib3==1.26.20
xlrd==2.0.1
zipp==3.6.0

name: prwlr
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - charset-normalizer==2.0.12
      - cycler==0.11.0
      - decorator==4.4.2
      - dill==0.3.4
      - idna==3.10
      - importlib-metadata==4.8.3
      - importlib-resources==5.4.0
      - iniconfig==1.1.1
      - kiwisolver==1.3.1
      - matplotlib==3.3.4
      - multiprocess==0.70.12.2
      - networkx==2.5.1
      - nose==1.3.7
      - numpy==1.19.5
      - packaging==21.3
      - pandas==0.23.0
      - pathos==0.2.8
      - pillow==8.4.0
      - pluggy==1.0.0
      - pox==0.3.0
      - ppft==1.6.6.4
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.27.1
      - scipy==1.5.4
      - six==1.17.0
      - tomli==1.2.3
      - tqdm==4.64.1
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - xlrd==2.0.1
      - zipp==3.6.0
prefix: /opt/conda/envs/prwlr

tests/tests.py::CoreTests::test_save_network
tests/tests.py::UtilsTests::test_all_possible_combinations_counter tests/tests.py::UtilsTests::test_isiniterable tests/tests.py::UtilsTests::test_remove_char tests/tests.py::UtilsTests::test_remove_from_list tests/tests.py::ApisTests::test_get_KOs_db_X_ref tests/tests.py::ApisTests::test_get_org_db_X_ref tests/tests.py::ApisTests::test_get_organisms_ids tests/tests.py::ApisTests::test_org_name_2_kegg_id tests/tests.py::DatabasesTests::test_parse_database tests/tests.py::DatabasesTests::test_parse_organism_info tests/tests.py::SGA1Tests::test_parse tests/tests.py::SGA2Tests::test_parse tests/tests.py::AnyNetworkTests::test_parse tests/tests.py::BioprocessesTests::test_parse tests/tests.py::ProfileTests::test___eq__ tests/tests.py::ProfileTests::test__bind tests/tests.py::ProfileTests::test__convert tests/tests.py::ProfileTests::test_calculate_pss tests/tests.py::ProfileTests::test_calculate_pss_ignore tests/tests.py::ProfileTests::test_get_absent tests/tests.py::ProfileTests::test_get_present tests/tests.py::ProfileTests::test_isall tests/tests.py::ProfileTests::test_isany tests/tests.py::ProfileTests::test_to_array tests/tests.py::ProfileTests::test_to_list tests/tests.py::ProfileTests::test_to_series tests/tests.py::ProfileTests::test_to_string tests/tests.py::ProfileTests::test_to_tuple tests/tests.py::StatsTests::test_binomial_pss_test tests/tests.py::CoreTests::test_read_network tests/tests.py::CoreTests::test_read_profiles tests/tests.py::CoreTests::test_save_profiles
prwlr/core.py
prwlr/core.py