Skip to content

Commit

Permalink
SNOW-1748281: Add support for Series.str.center (#2731)
Browse files Browse the repository at this point in the history
<!---
Please answer these questions before creating your pull request. Thanks!
--->

1. Which Jira issue is this PR addressing? Make sure that there is an
accompanying issue to your PR.

   <!---
   In this section, please add a Snowflake Jira issue number.

Note that if a corresponding GitHub issue exists, you should still
include
   the Snowflake Jira issue number. For example, for GitHub issue
#1400, you should
   add "SNOW-1335071" here.
    --->

   Fixes SNOW-1748281

2. Fill out the following pre-review checklist:

- [x] I am adding a new automated test(s) to verify correctness of my
new code
- [ ] If this test skips Local Testing mode, I'm requesting review from
@snowflakedb/local-testing
   - [ ] I am adding new logging messages
   - [ ] I am adding a new telemetry message
   - [ ] I am adding new credentials
   - [ ] I am adding a new dependency
- [ ] If this is a new feature/behavior, I'm adding the Local Testing
parity changes.
- [ ] I acknowledge that I have ensured my changes to be thread-safe.
Follow the link for more information: [Thread-safe Developer
Guidelines](https://github.com/snowflakedb/snowpark-python/blob/main/CONTRIBUTING.md#thread-safe-development)

3. Please describe how your code solves the related issue.

   Add support for Series.str.center.
  • Loading branch information
sfc-gh-helmeleegy authored Dec 10, 2024
1 parent e57cb78 commit 99dde61
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#### New Features

- Added support for `Series.str.ljust` and `Series.str.rjust`.
- Added support for `Series.str.center`.


## 1.26.0 (2024-12-05)
Expand Down
2 changes: 1 addition & 1 deletion docs/source/modin/supported/series_str_supported.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ the method in the left column.
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``cat`` | N | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``center`` | N | |
| ``center`` | Y | |
+-----------------------------+---------------------------------+----------------------------------------------------+
| ``contains`` | P | ``N`` if the `na` parameter is set to a non-bool |
| | | value. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16253,8 +16253,39 @@ def str___getitem__(self, key: Union[Scalar, slice]) -> "SnowflakeQueryCompiler"
raise ValueError("slice step cannot be zero")
return self.str_slice(key.start, key.stop, key.step)

def str_center(self, width: int, fillchar: str = " ") -> None:
ErrorMessage.method_not_implemented_error("center", "Series.str")
def str_center(self, width: int, fillchar: str = " ") -> "SnowflakeQueryCompiler":
if not isinstance(width, int):
raise TypeError(
f"width must be of integer type, not {type(width).__name__}"
)
if not isinstance(fillchar, str):
raise TypeError(
f"fillchar must be of integer type, not {type(fillchar).__name__}"
)
if len(fillchar) != 1:
raise TypeError("fillchar must be a character, not str")

def output_col(column: SnowparkColumn) -> SnowparkColumn:
new_col = rpad(
lpad(
column,
greatest(
length(column),
length(column)
+ (pandas_lit(width) - length(column) - pandas_lit(1))
/ pandas_lit(2),
),
pandas_lit(fillchar),
),
greatest(length(column), pandas_lit(width)),
pandas_lit(fillchar),
)
return self._replace_non_str(column, new_col)

new_internal_frame = self._modin_frame.apply_snowpark_function_to_columns(
output_col
)
return SnowflakeQueryCompiler(new_internal_frame)

def str_contains(
self,
Expand Down Expand Up @@ -16473,6 +16504,12 @@ def str_ljust(self, width: int, fillchar: str = " ") -> "SnowflakeQueryCompiler"
raise TypeError(
f"width must be of integer type, not {type(width).__name__}"
)
if not isinstance(fillchar, str):
raise TypeError(
f"fillchar must be of integer type, not {type(fillchar).__name__}"
)
if len(fillchar) != 1:
raise TypeError("fillchar must be a character, not str")

def output_col(column: SnowparkColumn) -> SnowparkColumn:
new_col = rpad(
Expand Down Expand Up @@ -16507,6 +16544,12 @@ def str_rjust(self, width: int, fillchar: str = " ") -> "SnowflakeQueryCompiler"
raise TypeError(
f"width must be of integer type, not {type(width).__name__}"
)
if not isinstance(fillchar, str):
raise TypeError(
f"fillchar must be of integer type, not {type(fillchar).__name__}"
)
if len(fillchar) != 1:
raise TypeError("fillchar must be a character, not str")

def output_col(column: SnowparkColumn) -> SnowparkColumn:
new_col = lpad(
Expand Down
46 changes: 45 additions & 1 deletion src/snowflake/snowpark/modin/plugin/docstrings/series_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,51 @@ def pad():
pass

def center():
pass
"""
Pad left and right side of strings in the Series/Index.
Equivalent to str.center().
Parameters
----------
width : int
Minimum width of resulting string; additional characters will be filled with fillchar.
fillchar : str
Additional character for filling, default is whitespace.
Returns
-------
Series/Index of objects.
Examples
--------
For Series.str.center:
>>> ser = pd.Series(['dog', 'bird', 'mouse'])
>>> ser.str.center(8, fillchar='.')
0 ..dog...
1 ..bird..
2 .mouse..
dtype: object
For Series.str.ljust:
>>> ser = pd.Series(['dog', 'bird', 'mouse'])
>>> ser.str.ljust(8, fillchar='.')
0 dog.....
1 bird....
2 mouse...
dtype: object
For Series.str.rjust:
>>> ser = pd.Series(['dog', 'bird', 'mouse'])
>>> ser.str.rjust(8, fillchar='.')
0 .....dog
1 ....bird
2 ...mouse
dtype: object
"""

def ljust():
"""
Expand Down
10 changes: 6 additions & 4 deletions tests/integ/modin/series/test_str_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,11 +422,11 @@ def test_str_no_params(func):
)


@pytest.mark.parametrize("func", ["ljust", "rjust"])
@pytest.mark.parametrize("func", ["center", "ljust", "rjust"])
@pytest.mark.parametrize("width", [-1, 0, 1, 10, 100])
@pytest.mark.parametrize("fillchar", [" ", "#"])
@sql_count_checker(query_count=1)
def test_str_ljust_rjust(func, width, fillchar):
def test_str_center_ljust_rjust(func, width, fillchar):
native_ser = native_pd.Series(TEST_DATA)
snow_ser = pd.Series(native_ser)
eval_snowpark_pandas_result(
Expand All @@ -436,18 +436,20 @@ def test_str_ljust_rjust(func, width, fillchar):
)


@pytest.mark.parametrize("func", ["ljust", "rjust"])
@pytest.mark.parametrize("func", ["center", "ljust", "rjust"])
@pytest.mark.parametrize(
"width, fillchar",
[
(None, " "),
("ten", " "),
(10, ""),
(10, "ab"),
(10, None),
(10, 10),
],
)
@sql_count_checker(query_count=0)
def test_str_ljust_rjust_neg(func, width, fillchar):
def test_str_center_ljust_rjust_neg(func, width, fillchar):
native_ser = native_pd.Series(TEST_DATA)
snow_ser = pd.Series(native_ser)
with pytest.raises(TypeError):
Expand Down
6 changes: 0 additions & 6 deletions tests/unit/modin/test_series_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def test_str_cat_no_others(mock_str_register, mock_series):
(lambda s: s.str.rsplit("_", n=1), "rsplit"),
(lambda s: s.str.join("_"), "join"),
(lambda s: s.str.pad(10), "pad"),
(lambda s: s.str.center(10), "center"),
(lambda s: s.str.zfill(8), "zfill"),
(lambda s: s.str.wrap(3), "wrap"),
(lambda s: s.str.slice_replace(start=3, stop=5, repl="abc"), "slice_replace"),
Expand Down Expand Up @@ -105,11 +104,6 @@ def test_str_methods_with_dataframe_return(func, func_name, mock_series):
TypeError,
"fillchar must be a character, not str",
),
(
lambda s: s.str.center(8, fillchar="abc"),
TypeError,
"fillchar must be a character, not str",
),
(lambda s: s.str.wrap(-1), ValueError, r"invalid width -1 \(must be > 0\)"),
(
lambda s: s.str.count(12),
Expand Down

0 comments on commit 99dde61

Please sign in to comment.