Repository: pyjanitor-devs/pyjanitor

Issue:
[ENH] Series toset() functionality
# Brief Description

<!-- Please provide a brief description of what you'd like to propose. -->

I would like to propose toset() functionality similar to [tolist()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.tolist.html). 
Basically it will be a function call to tolist and then conversion to set.
Note: if the collection has no hashable member it will raise an exception.

# Example API

<!-- One of the selling points of pyjanitor is the API. Hence, we guard the API very carefully, and want to
make sure that it is accessible and understandable to many people. Please provide a few examples of what the API
of the new function you're proposing will look like. We have provided an example that you should modify. -->

Please modify the example API below to illustrate your proposed API, and then delete this sentence.

```python
# convert series to a set
df['col1'].toset()


[ENH] Series toset() functionality
# Brief Description

<!-- Please provide a brief description of what you'd like to propose. -->

I would like to propose toset() functionality similar to [tolist()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.tolist.html). 
Basically it will be a function call to tolist and then conversion to set.
Note: if the collection has no hashable member it will raise an exception.

# Example API

<!-- One of the selling points of pyjanitor is the API. Hence, we guard the API very carefully, and want to
make sure that it is accessible and understandable to many people. Please provide a few examples of what the API
of the new function you're proposing will look like. We have provided an example that you should modify. -->

Please modify the example API below to illustrate your proposed API, and then delete this sentence.

```python
# convert series to a set
df['col1'].toset()


[INF] Make requirements.txt smaller
Follow-up from #257 

The idea is to have feature-specific requirements.txt. Such as for biology, specifically requires biopython.

so we can install the package per feature as needed, such as with extra biology. It goes `pip install "pyjanitor[biology]"`

The example of such implementations in `setup.py` is available at this link: https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies


Discussion:


Makes a lot of sense to me. We also have that chemistry module in there, and I'm guessing both of those might be somewhat niche for what the average user of pyjanitor's use case is.

Also, the current usage for `import_message` in chemistry and biology only references conda packages to be installed (rather than both pip & conda depending on the user's env). Might be something else to include in this general goal of making pyjanitor more modularizable.
I would love to work on this :)
Assigning this to you, @eyaltrabelsi!

Resolving patch:
diff --git a/janitor/functions.py b/janitor/functions.py
--- a/janitor/functions.py
+++ b/janitor/functions.py
@@ -6,7 +6,7 @@
 import warnings
 from fnmatch import translate
 from functools import partial, reduce
-from typing import Any, Callable, Dict, Iterable, List, Tuple, Union
+from typing import Any, Callable, Dict, Iterable, List, Tuple, Union, Set
 
 import numpy as np
 import pandas as pd
@@ -3485,3 +3485,39 @@ def count_cumulative_unique(
     )
 
     return df
+
+
+@pf.register_series_method
+def toset(series: pd.Series) -> Set:
+    """
+    Return a set of the values.
+
+    These are each a scalar type, which is a Python scalar
+    (for str, int, float) or a pandas scalar
+    (for Timestamp/Timedelta/Interval/Period)
+
+    Functional usage example:
+
+    .. code-block:: python
+
+        import pandas as pd
+        import janitor as jn
+
+        series = pd.Series(...)
+        s = jn.functions.toset(series=series)
+
+    Method chaining usage example:
+
+    .. code-block:: python
+
+        import pandas as pd
+        import janitor.functions
+
+        series = pd.Series(...)
+        s = series.toset()
+
+    :param series: A pandas series.
+    :returns: A set of values.
+    """
+
+    return set(series.tolist())


Test patch:
diff --git a/tests/functions/test_toset.py b/tests/functions/test_toset.py
new file mode 100644
--- /dev/null
+++ b/tests/functions/test_toset.py
@@ -0,0 +1,11 @@
+import pandas as pd
+import pytest
+
+
+@pytest.mark.functions
+def test_coalesce_with_title():
+    s = pd.Series([1, 2, 3, 5, 5], index=["a", "b", "c", "d", "e"]).toset()
+
+    assert isinstance(s, set)
+    assert len(s) == 4
+    assert s == set([1, 2, 3, 5])