-
-
Notifications
You must be signed in to change notification settings - Fork 18.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
REG: DataFrame/Series.transform with list and non-list dict values #40090
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -280,7 +280,7 @@ def transform_dict_like(self, func): | |
if len(func) == 0: | ||
raise ValueError("No transform functions were provided") | ||
|
||
self.validate_dictlike_arg("transform", obj, func) | ||
func = self.validate_dictlike_arg("transform", obj, func) | ||
|
||
results: Dict[Hashable, FrameOrSeriesUnion] = {} | ||
for name, how in func.items(): | ||
|
@@ -421,32 +421,17 @@ def agg_dict_like(self, _axis: int) -> FrameOrSeriesUnion: | |
------- | ||
Result of aggregation. | ||
""" | ||
from pandas.core.reshape.concat import concat | ||
|
||
obj = self.obj | ||
arg = cast(AggFuncTypeDict, self.f) | ||
|
||
is_aggregator = lambda x: isinstance(x, (list, tuple, dict)) | ||
|
||
if _axis != 0: # pragma: no cover | ||
raise ValueError("Can only pass dict with axis=0") | ||
|
||
selected_obj = obj._selected_obj | ||
|
||
self.validate_dictlike_arg("agg", selected_obj, arg) | ||
|
||
# if we have a dict of any non-scalars | ||
# eg. {'A' : ['mean']}, normalize all to | ||
# be list-likes | ||
# Cannot use arg.values() because arg may be a Series | ||
if any(is_aggregator(x) for _, x in arg.items()): | ||
new_arg: AggFuncTypeDict = {} | ||
for k, v in arg.items(): | ||
if not isinstance(v, (tuple, list, dict)): | ||
new_arg[k] = [v] | ||
else: | ||
new_arg[k] = v | ||
arg = new_arg | ||
|
||
from pandas.core.reshape.concat import concat | ||
arg = self.validate_dictlike_arg("agg", selected_obj, arg) | ||
|
||
if selected_obj.ndim == 1: | ||
# key only used for output | ||
|
@@ -542,12 +527,13 @@ def maybe_apply_multiple(self) -> Optional[FrameOrSeriesUnion]: | |
|
||
def validate_dictlike_arg( | ||
self, how: str, obj: FrameOrSeriesUnion, func: AggFuncTypeDict | ||
) -> None: | ||
) -> AggFuncTypeDict: | ||
""" | ||
Raise if dict-like argument is invalid. | ||
Handler for dict-like argument. | ||
|
||
Ensures that necessary columns exist if obj is a DataFrame, and | ||
that a nested renamer is not passed. | ||
that a nested renamer is not passed. Also normalizes to all lists | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe not here if too many changes for a backport, but maybe change function name to say There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @simonjayhawkins Thanks for the suggestion. That's actually how I started this out, but then changed it to validate recalling Related: #19171 |
||
when values consists of a mix of list and non-lists. | ||
""" | ||
assert how in ("apply", "agg", "transform") | ||
|
||
|
@@ -567,6 +553,23 @@ def validate_dictlike_arg( | |
cols_sorted = list(safe_sort(list(cols))) | ||
raise KeyError(f"Column(s) {cols_sorted} do not exist") | ||
|
||
is_aggregator = lambda x: isinstance(x, (list, tuple, dict)) | ||
|
||
# if we have a dict of any non-scalars | ||
# eg. {'A' : ['mean']}, normalize all to | ||
# be list-likes | ||
# Cannot use func.values() because arg may be a Series | ||
if any(is_aggregator(x) for _, x in func.items()): | ||
new_func: AggFuncTypeDict = {} | ||
for k, v in func.items(): | ||
if not is_aggregator(v): | ||
# mypy can't realize v is not a list here | ||
new_func[k] = [v] # type:ignore[list-item] | ||
else: | ||
new_func[k] = v | ||
func = new_func | ||
return func | ||
|
||
|
||
class FrameApply(Apply): | ||
obj: DataFrame | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you put in 1.2.3