Repository: dask/dask

Issue:
Add support for `add_prefix and `add_suffix`
I tend to use these before doing DataFrame merges so that my column names (of the right merged dataframe) retain some semantic notion of where they came from. Switched to Dask and noticed these don't exist.

Is that a conscious decision to exclude or would you be welcome to its addition?

I tried a brief google search and tried filtering through the issues on this repo, but forgive me if I've missed an existing discussion.

* [`pandas.DataFrame.add_prefix`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.add_prefix.html)
* [`pandas.DataFrame.add_suffix`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.add_suffix.html)


Discussion:
Thanks for raising an issue @mzjp2! Not a conscious decision, I suspect it's just nobody has gotten around to implementing these methods.

It seems like they could be implemented with `map_partitions` similar to `abs`

https://github.com/dask/dask/blob/0b33708f4627c3f9c7613c9554d1033db147d4b0/dask/dataframe/core.py#L1663-L1667

or several other methods in the `dask/dataframe/core.py`. 

Are you interested in working on this? No worries if not 
Oh hey @jrbourbeau! We've spoke over at Zarr!

> Are you interested in working on this?

Yes, absolutely! Though I'm _totally_ new to the codebase here, but would love to get stuck in and have a go. Thanks for the pointer to `abs`.

Good to see you here too : )

Sounds good! Our contributing docs are at https://docs.dask.org/en/latest/develop.html. Feel free to open up a WIP PR if you get stuck or have any questions  

Resolving patch:
diff --git a/dask/dataframe/core.py b/dask/dataframe/core.py
--- a/dask/dataframe/core.py
+++ b/dask/dataframe/core.py
@@ -1679,6 +1679,20 @@ def _reduction_agg(self, name, axis=None, skipna=True, split_every=False, out=No
                 result.divisions = (self.columns.min(), self.columns.max())
             return handle_out(out, result)
 
+    @derived_from(pd.DataFrame)
+    def add_prefix(self, prefix):
+        res = self.map_partitions(M.add_prefix, prefix)
+        if self.known_divisions and is_series_like(self):
+            res.divisions = tuple(prefix + str(division) for division in self.divisions)
+        return res
+
+    @derived_from(pd.DataFrame)
+    def add_suffix(self, suffix):
+        res = self.map_partitions(M.add_suffix, suffix)
+        if self.known_divisions and is_series_like(self):
+            res.divisions = tuple(str(division) + suffix for division in self.divisions)
+        return res
+
     @derived_from(pd.DataFrame)
     def abs(self):
         _raise_if_object_series(self, "abs")


Test patch:
diff --git a/dask/dataframe/tests/test_dataframe.py b/dask/dataframe/tests/test_dataframe.py
--- a/dask/dataframe/tests/test_dataframe.py
+++ b/dask/dataframe/tests/test_dataframe.py
@@ -2862,6 +2862,20 @@ def test_applymap():
     assert_eq(ddf.applymap(lambda x: (x, x)), df.applymap(lambda x: (x, x)))
 
 
+def test_add_prefix():
+    df = pd.DataFrame({"x": [1, 2, 3, 4, 5], "y": [4, 5, 6, 7, 8]})
+    ddf = dd.from_pandas(df, npartitions=2)
+    assert_eq(ddf.add_prefix("abc"), df.add_prefix("abc"))
+    assert_eq(ddf.x.add_prefix("abc"), df.x.add_prefix("abc"))
+
+
+def test_add_suffix():
+    df = pd.DataFrame({"x": [1, 2, 3, 4, 5], "y": [4, 5, 6, 7, 8]})
+    ddf = dd.from_pandas(df, npartitions=2)
+    assert_eq(ddf.add_suffix("abc"), df.add_suffix("abc"))
+    assert_eq(ddf.x.add_suffix("abc"), df.x.add_suffix("abc"))
+
+
 def test_abs():
     df = pd.DataFrame(
         {