pep8speaks: Hello @ksunden! Thanks for submitting the PR.

 - In the file [`WrightTools/data/_data.py`](https://github.com/wright-group/WrightTools/blob/6ebf5e1f7c3278d932b53a62d9ea7785dc2aafc7/WrightTools/data/_data.py), following are the PEP8 issues :

> [Line 1506:91](https://github.com/wright-group/WrightTools/blob/6ebf5e1f7c3278d932b53a62d9ea7785dc2aafc7/WrightTools/data/_data.py#L1506): [W291](https://duckduckgo.com/?q=pep8%20W291) trailing whitespace
> [Line 1507:25](https://github.com/wright-group/WrightTools/blob/6ebf5e1f7c3278d932b53a62d9ea7785dc2aafc7/WrightTools/data/_data.py#L1507): [E128](https://duckduckgo.com/?q=pep8%20E128) continuation line under-indented for visual indent

 - In the file [`WrightTools/exceptions.py`](https://github.com/wright-group/WrightTools/blob/6ebf5e1f7c3278d932b53a62d9ea7785dc2aafc7/WrightTools/exceptions.py), following are the PEP8 issues :

> [Line 29:1](https://github.com/wright-group/WrightTools/blob/6ebf5e1f7c3278d932b53a62d9ea7785dc2aafc7/WrightTools/exceptions.py#L29): [E302](https://duckduckgo.com/?q=pep8%20E302) expected 2 blank lines, found 1


diff --git a/WrightTools/data/_data.py b/WrightTools/data/_data.py
index 8915e48..c023b51 100644
--- a/WrightTools/data/_data.py
+++ b/WrightTools/data/_data.py
@@ -1203,12 +1203,10 @@ class Data:
 
         Notes
         -----
-
         m-factors originally derived by Carlson and Wright. [1]_
 
         References
         ----------
-
         .. [1] **Absorption and Coherent Interference Effects in Multiply Resonant
                Four-Wave Mixing Spectroscopy**
                Roger J. Carlson, and John C. Wright
@@ -1520,6 +1518,30 @@ class Data:
         # finish
         self._update()
 
+    def rename_attrs(self, **kwargs):
+        """Rename a set of attributes.
+
+        Keyword Arguments
+        -----------------
+        Each argument should have the key of a current axis or channel,
+            and a value which is a string of its new name.
+
+        The name will be set to str(val), and its natural naming identifier
+        will be wt.kit.string2identifier(str(val))
+        """
+        changed = kwargs.keys()
+        for k, v in kwargs.items():
+            if getattr(self, k).__class__ not in (Channel, Axis):
+                raise TypeError("Attribute for key %s: expected {Channel, Axis}, got %s" %
+                                (k, getattr(self, k).__class__))
+            if v not in changed and hasattr(self, v):
+                raise wt_exceptions.NameNotUniqueError(v)
+        for k, v in kwargs.items():
+            axis = getattr(self, k)
+            axis.name = str(v)
+            delattr(self, k)
+        self._update()
+
     def save(self, filepath=None, verbose=True):
         """Save using the `pickle`__ module.
 
diff --git a/WrightTools/exceptions.py b/WrightTools/exceptions.py
index 3c25ce4..8f3fa78 100644
--- a/WrightTools/exceptions.py
+++ b/WrightTools/exceptions.py
@@ -44,6 +44,21 @@ class FileNotFound(Exception):
         Exception.__init__(self, message)
 
 
+class NameNotUniqueError(Exception):
+    """NameNotUniqueError."""
+
+    def __init__(self, name):
+        """Format a Name Not Unique Error.
+
+        Parameters
+        ----------
+        name : string
+            Name of an attribute which causes a duplication.
+        """
+        message = 'Name {} results in a duplicate'.format(name)
+        Exception.__init__(self, message)
+
+
 # --- custom warnings -----------------------------------------------------------------------------
 
 

rename methods
`data.rename_channel` and `data.rename_axis`

accept kwargs with key oldname and value newname

if newname already in names and not ALSO being renamed, raise helpful exception

remember to call `data._update`

not necessarily clear how to handle `axis.label_seed`
diff --git a/tests/data/rename_attrs.py b/tests/data/rename_attrs.py
new file mode 100644
index 0000000..f032f7d
--- /dev/null
+++ b/tests/data/rename_attrs.py
@@ -0,0 +1,30 @@
+"""test rename_attrs."""
+
+
+# --- import --------------------------------------------------------------------------------------
+
+
+import WrightTools as wt
+from WrightTools import datasets
+
+
+# --- test ----------------------------------------------------------------------------------------
+
+
+def test_rename():
+    p = datasets.PyCMDS.wm_w2_w1_000
+    data = wt.data.from_PyCMDS(p)
+    data.rename_attrs(w1='w2', w2='w1')
+    assert data.shape == (35, 11, 11)
+    assert data.axis_names == ['wm', 'w1', 'w2']
+
+
+def test_error():
+    p = datasets.PyCMDS.wm_w2_w1_000
+    data = wt.data.from_PyCMDS(p)
+    try:
+        data.rename_attrs(w1='w2')
+    except wt.exceptions.NameNotUniqueError:
+        assert True
+    else:
+        assert False

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
appdirs==1.4.4
attrs==22.2.0
cached-property==1.5.2
certifi==2021.5.30
cycler==0.11.0
h5py==3.1.0
imageio==2.15.0
importlib-metadata==4.8.3
iniconfig==1.1.1
kiwisolver==1.3.1
matplotlib==3.3.4
numpy==1.19.5
packaging==21.3
Pillow==8.4.0
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
pytz==2025.2
scipy==1.5.4
six==1.17.0
tomli==1.2.3
typing_extensions==4.1.1
-e git+https://github.com/wright-group/WrightTools.git@2be1155987558d6c7358654e9f26068f5359df96#egg=WrightTools
zipp==3.6.0

name: WrightTools
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:
      - appdirs==1.4.4
      - attrs==22.2.0
      - cached-property==1.5.2
      - cycler==0.11.0
      - h5py==3.1.0
      - imageio==2.15.0
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - kiwisolver==1.3.1
      - matplotlib==3.3.4
      - numpy==1.19.5
      - packaging==21.3
      - pillow==8.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - scipy==1.5.4
      - six==1.17.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/WrightTools

tests/data/rename_attrs.py::test_rename tests/data/rename_attrs.py::test_error
WrightTools/exceptions.py WrightTools/data/_data.py
WrightTools/exceptions.py WrightTools/data/_data.py