From 7e42340515cf5961d7ab92c983e80045e8ef1e6c Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 14 Nov 2019 09:36:45 -0800 Subject: [PATCH 01/10] CLN: reshape --- pandas/core/reshape/concat.py | 30 +++--------------------------- pandas/core/reshape/merge.py | 24 +++++++++++++----------- pandas/core/reshape/pivot.py | 26 +++++++++++++++++++------- pandas/core/reshape/tile.py | 6 +++--- 4 files changed, 38 insertions(+), 48 deletions(-) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 3c1b2b1eb11d2..749688aa563b4 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -437,13 +437,13 @@ def get_result(self): mgr = self.objs[0]._data.concat( [x._data for x in self.objs], self.new_axes ) - cons = _get_series_result_type(mgr, self.objs) + cons = self.objs[0]._constructor return cons(mgr, name=name).__finalize__(self, method="concat") # combine as columns in a frame else: data = dict(zip(range(len(self.objs)), self.objs)) - cons = _get_series_result_type(data) + cons = DataFrame index, columns = self.new_axes df = cons(data, index=index) @@ -473,7 +473,7 @@ def get_result(self): if not self.copy: new_data._consolidate_inplace() - cons = _get_frame_result_type(new_data, self.objs) + cons = self.objs[0]._constructor return cons._from_axes(new_data, self.new_axes).__finalize__( self, method="concat" ) @@ -706,27 +706,3 @@ def _make_concat_multiindex(indexes, keys, levels=None, names=None) -> MultiInde return MultiIndex( levels=new_levels, codes=new_codes, names=new_names, verify_integrity=False ) - - -def _get_series_result_type(result, objs=None): - """ - return appropriate class of Series concat - input is either dict or array-like - """ - # TODO: See if we can just inline with _constructor_expanddim - # now that sparse is removed. - - # concat Series with axis 1 - if isinstance(result, dict): - return DataFrame - - # otherwise it is a SingleBlockManager (axis = 0) - return objs[0]._constructor - - -def _get_frame_result_type(result, objs): - """ - return appropriate class of DataFrame-like concat - """ - # TODO: just inline this as _constructor. - return objs[0] diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py index 76c4b328eb4db..fc9faba8af827 100644 --- a/pandas/core/reshape/merge.py +++ b/pandas/core/reshape/merge.py @@ -92,7 +92,7 @@ def merge( def _groupby_and_merge( - by, on, left, right, _merge_pieces, check_duplicates: bool = True + by, on, left, right: "DataFrame", _merge_pieces, check_duplicates: bool = True ): """ groupby & merge; we are always performing a left-by type operation @@ -1299,11 +1299,13 @@ def _get_join_indexers( right_keys ), "left_key and right_keys must be the same length" - # bind `sort` arg. of _factorize_keys - fkeys = partial(_factorize_keys, sort=sort) - # get left & right join labels and num. of levels at each location - llab, rlab, shape = map(list, zip(*map(fkeys, left_keys, right_keys))) + mapped = ( + _factorize_keys(left_keys[n], right_keys[n], sort=sort) + for n in range(len(left_keys)) + ) + zipped = zip(*mapped) + llab, rlab, shape = [list(x) for x in zipped] # get flat i8 keys from label lists lkey, rkey = _get_join_keys(llab, rlab, shape, sort) @@ -1311,7 +1313,7 @@ def _get_join_indexers( # factorize keys to a dense i8 space # `count` is the num. of unique keys # set(lkey) | set(rkey) == range(count) - lkey, rkey, count = fkeys(lkey, rkey) + lkey, rkey, count = _factorize_keys(lkey, rkey, sort=sort) # preserve left frame order if how == 'left' and sort == False kwargs = copy.copy(kwargs) @@ -1775,11 +1777,11 @@ def flip(xs): def _get_multiindex_indexer(join_keys, index: MultiIndex, sort: bool): - # bind `sort` argument - fkeys = partial(_factorize_keys, sort=sort) - # left & right join labels and num. of levels at each location - mapped = (fkeys(index.levels[n], join_keys[n]) for n in range(len(index.levels))) + mapped = ( + _factorize_keys(index.levels[n], join_keys[n], sort=sort) + for n in range(len(index.levels)) + ) zipped = zip(*mapped) rcodes, lcodes, shape = [list(x) for x in zipped] if sort: @@ -1804,7 +1806,7 @@ def _get_multiindex_indexer(join_keys, index: MultiIndex, sort: bool): lkey, rkey = _get_join_keys(lcodes, rcodes, shape, sort) # factorize keys to a dense i8 space - lkey, rkey, count = fkeys(lkey, rkey) + lkey, rkey, count = _factorize_keys(lkey, rkey, sort=sort) return libjoin.left_outer_join(lkey, rkey, count, sort=sort) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 404292fe4d539..336a2fa27cc89 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -1,3 +1,5 @@ +from typing import Tuple, Union, Dict, Callable + import numpy as np from pandas.util._decorators import Appender, Substitution @@ -187,7 +189,7 @@ def _add_margins( cols, aggfunc, observed=None, - margins_name="All", + margins_name: str = "All", fill_value=None, ): if not isinstance(margins_name, str): @@ -207,7 +209,9 @@ def _add_margins( raise ValueError(msg) if len(rows) > 1: - key = (margins_name,) + ("",) * (len(rows) - 1) + key = (margins_name,) + ("",) * ( + len(rows) - 1 + ) # type: Union[str, Tuple[str, ...]] else: key = margins_name @@ -266,7 +270,7 @@ def _add_margins( return result -def _compute_grand_margin(data, values, aggfunc, margins_name="All"): +def _compute_grand_margin(data, values, aggfunc, margins_name: str = "All"): if values: grand_margin = {} @@ -289,7 +293,15 @@ def _compute_grand_margin(data, values, aggfunc, margins_name="All"): def _generate_marginal_results( - table, data, values, rows, cols, aggfunc, observed, grand_margin, margins_name="All" + table, + data, + values, + rows, + cols, + aggfunc, + observed, + grand_margin, + margins_name: str = "All", ): if len(cols) > 0: # need to "interleave" the margins @@ -353,7 +365,7 @@ def _all_key(key): def _generate_marginal_results_without_values( - table, data, rows, cols, aggfunc, observed, margins_name="All" + table, data, rows, cols, aggfunc, observed, margins_name: str = "All" ): if len(cols) > 0: # need to "interleave" the margins @@ -582,7 +594,7 @@ def crosstab( return table -def _normalize(table, normalize, margins, margins_name="All"): +def _normalize(table, normalize, margins: bool, margins_name="All"): if not isinstance(normalize, (bool, str)): axis_subs = {0: "index", 1: "columns"} @@ -598,7 +610,7 @@ def _normalize(table, normalize, margins, margins_name="All"): "all": lambda x: x / x.sum(axis=1).sum(axis=0), "columns": lambda x: x / x.sum(), "index": lambda x: x.div(x.sum(axis=1), axis=0), - } + } # type: Dict[Union[bool, str], Callable] normalizers[True] = normalizers["all"] diff --git a/pandas/core/reshape/tile.py b/pandas/core/reshape/tile.py index 073bb4707f890..bfaa49dd576dc 100644 --- a/pandas/core/reshape/tile.py +++ b/pandas/core/reshape/tile.py @@ -496,7 +496,7 @@ def _convert_bin_to_datelike_type(bins, dtype): def _format_labels( - bins, precision, right: bool = True, include_lowest: bool = False, dtype=None + bins, precision: int, right: bool = True, include_lowest: bool = False, dtype=None ): """ based on the dtype, return our labels """ @@ -565,7 +565,7 @@ def _postprocess_for_cut(fac, bins, retbins: bool, dtype, original): return fac, bins -def _round_frac(x, precision): +def _round_frac(x, precision: int): """ Round the fractional part of the given number """ @@ -580,7 +580,7 @@ def _round_frac(x, precision): return np.around(x, digits) -def _infer_precision(base_precision, bins): +def _infer_precision(base_precision: int, bins) -> int: """Infer an appropriate precision for _round_frac """ for precision in range(base_precision, 20): From 1f24020fa46d5af3e17941142e5c28a2c208ede4 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 14 Nov 2019 10:31:58 -0800 Subject: [PATCH 02/10] typing in reshape --- pandas/core/indexes/api.py | 2 +- pandas/core/reshape/concat.py | 6 +++--- pandas/core/reshape/melt.py | 12 ++++++------ pandas/core/reshape/pivot.py | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pandas/core/indexes/api.py b/pandas/core/indexes/api.py index 86d55ce2e7cc3..d985ee31c53d7 100644 --- a/pandas/core/indexes/api.py +++ b/pandas/core/indexes/api.py @@ -107,7 +107,7 @@ def _get_distinct_objs(objs): return res -def _get_combined_index(indexes, intersect=False, sort=False): +def _get_combined_index(indexes, intersect: bool = False, sort=False) -> Index: """ Return the union or intersection of indexes. diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 749688aa563b4..9323ec8d9fe67 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -520,7 +520,7 @@ def _get_new_axes(self): new_axes[self.axis] = self._get_concat_axis() return new_axes - def _get_comb_axis(self, i): + def _get_comb_axis(self, i: int): data_axis = self.objs[0]._get_block_manager_axis(i) try: return _get_objs_combined_axis( @@ -530,7 +530,7 @@ def _get_comb_axis(self, i): types = [type(x).__name__ for x in self.objs] raise TypeError("Cannot concatenate list of {types}".format(types=types)) - def _get_concat_axis(self): + def _get_concat_axis(self) -> Index: """ Return index to be used along concatenation axis. """ @@ -541,7 +541,7 @@ def _get_concat_axis(self): idx = ibase.default_index(len(self.objs)) return idx elif self.keys is None: - names = [None] * len(self.objs) + names = [None] * len(self.objs) # type: list num = 0 has_names = False for i, x in enumerate(self.objs): diff --git a/pandas/core/reshape/melt.py b/pandas/core/reshape/melt.py index 16c04454898db..cd93e6e7df9e5 100644 --- a/pandas/core/reshape/melt.py +++ b/pandas/core/reshape/melt.py @@ -10,7 +10,7 @@ from pandas.core.dtypes.missing import notna from pandas.core.arrays import Categorical -from pandas.core.frame import _shared_docs +from pandas.core.frame import DataFrame, _shared_docs from pandas.core.indexes.base import Index from pandas.core.reshape.concat import concat from pandas.core.tools.numeric import to_numeric @@ -21,13 +21,13 @@ % dict(caller="pd.melt(df, ", versionadded="", other="DataFrame.melt") ) def melt( - frame, + frame: DataFrame, id_vars=None, value_vars=None, var_name=None, value_name="value", col_level=None, -): +) -> DataFrame: # TODO: what about the existing index? # If multiindex, gather names of columns on all level for checking presence # of `id_vars` and `value_vars` @@ -119,7 +119,7 @@ def melt( return frame._constructor(mdata, columns=mcolumns) -def lreshape(data, groups, dropna=True, label=None): +def lreshape(data: DataFrame, groups, dropna: bool = True, label=None) -> DataFrame: """ Reshape long-format data to wide. Generalized inverse of DataFrame.pivot @@ -412,14 +412,14 @@ def wide_to_long(df, stubnames, i, j, sep: str = "", suffix: str = r"\d+"): two 2.9 """ - def get_var_names(df, stub, sep, suffix): + def get_var_names(df, stub: str, sep: str, suffix): regex = r"^{stub}{sep}{suffix}$".format( stub=re.escape(stub), sep=re.escape(sep), suffix=suffix ) pattern = re.compile(regex) return [col for col in df.columns if pattern.match(col)] - def melt_stub(df, stub, i, j, value_vars, sep: str): + def melt_stub(df, stub: str, i, j, value_vars, sep: str): newdf = melt( df, id_vars=i, diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 336a2fa27cc89..556edd9c435d7 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -1,4 +1,4 @@ -from typing import Tuple, Union, Dict, Callable +from typing import Callable, Dict, Tuple, Union import numpy as np @@ -677,7 +677,7 @@ def _normalize(table, normalize, margins: bool, margins_name="All"): return table -def _get_names(arrs, names, prefix="row"): +def _get_names(arrs, names, prefix: str = "row"): if names is None: names = [] for i, arr in enumerate(arrs): From 51276e311115e2d3f8d8b02063508b585869ee5d Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 14 Nov 2019 13:11:40 -0800 Subject: [PATCH 03/10] typings --- pandas/core/reshape/concat.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 9323ec8d9fe67..4a304f58b3861 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -1,7 +1,6 @@ """ concat routines """ - import warnings import numpy as np @@ -520,15 +519,11 @@ def _get_new_axes(self): new_axes[self.axis] = self._get_concat_axis() return new_axes - def _get_comb_axis(self, i: int): + def _get_comb_axis(self, i: int) -> Index: data_axis = self.objs[0]._get_block_manager_axis(i) - try: - return _get_objs_combined_axis( - self.objs, axis=data_axis, intersect=self.intersect, sort=self.sort - ) - except IndexError: - types = [type(x).__name__ for x in self.objs] - raise TypeError("Cannot concatenate list of {types}".format(types=types)) + return _get_objs_combined_axis( + self.objs, axis=data_axis, intersect=self.intersect, sort=self.sort + ) def _get_concat_axis(self) -> Index: """ From 68926f54acfb72eb476f8d1e018231e9fec62876 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 14 Nov 2019 13:16:23 -0800 Subject: [PATCH 04/10] annotaitons --- pandas/core/reshape/melt.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pandas/core/reshape/melt.py b/pandas/core/reshape/melt.py index cd93e6e7df9e5..189d3d578565a 100644 --- a/pandas/core/reshape/melt.py +++ b/pandas/core/reshape/melt.py @@ -1,4 +1,5 @@ import re +from typing import List import numpy as np @@ -35,6 +36,7 @@ def melt( cols = [x for c in frame.columns for x in c] else: cols = list(frame.columns) + if id_vars is not None: if not is_list_like(id_vars): id_vars = [id_vars] @@ -129,6 +131,8 @@ def lreshape(data: DataFrame, groups, dropna: bool = True, label=None) -> DataFr groups : dict {new_name : list_of_columns} dropna : boolean, default True + label : object, default None + Dummy kwarg, not used. Examples -------- @@ -188,7 +192,7 @@ def lreshape(data: DataFrame, groups, dropna: bool = True, label=None) -> DataFr return data._constructor(mdata, columns=id_cols + pivot_cols) -def wide_to_long(df, stubnames, i, j, sep: str = "", suffix: str = r"\d+"): +def wide_to_long(df: DataFrame, stubnames, i, j, sep: str = "", suffix: str = r"\d+"): r""" Wide panel to long format. Less flexible but more user-friendly than melt. @@ -412,7 +416,7 @@ def wide_to_long(df, stubnames, i, j, sep: str = "", suffix: str = r"\d+"): two 2.9 """ - def get_var_names(df, stub: str, sep: str, suffix): + def get_var_names(df, stub: str, sep: str, suffix) -> List[str]: regex = r"^{stub}{sep}{suffix}$".format( stub=re.escape(stub), sep=re.escape(sep), suffix=suffix ) From e9b981af7343fdd789f6fcd3f93d62d2d9f66ea1 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 14 Nov 2019 17:10:20 -0800 Subject: [PATCH 05/10] annotations --- pandas/core/reshape/concat.py | 1 + pandas/core/reshape/pivot.py | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 4a304f58b3861..63f90e9c7ec82 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -1,6 +1,7 @@ """ concat routines """ + import warnings import numpy as np diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 7435cdacb4daa..a3048903df473 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -1,4 +1,4 @@ -from typing import Callable, Dict, Tuple, Union +from typing import TYPE_CHECKING, Callable, Dict, Tuple, Union import numpy as np @@ -16,6 +16,9 @@ from pandas.core.reshape.util import cartesian_product from pandas.core.series import Series +if TYPE_CHECKING: + from pandas import DataFrame + # Note: We need to make sure `frame` is imported before `pivot`, otherwise # _shared_docs['pivot_table'] will not yet exist. TODO: Fix this dependency @@ -182,7 +185,7 @@ def pivot_table( def _add_margins( - table, + table: Union["Series", "DataFrame"], data, values, rows, @@ -202,8 +205,8 @@ def _add_margins( grand_margin = _compute_grand_margin(data, values, aggfunc, margins_name) - # could be passed a Series object with no 'columns' - if hasattr(table, "columns"): + if table.ndim == 2: + # i.e. DataFramae for level in table.columns.names[1:]: if margins_name in table.columns.get_level_values(level): raise ValueError(msg) @@ -220,7 +223,7 @@ def _add_margins( # one column in the data. Compute grand margin and return it. return table.append(Series({key: grand_margin[margins_name]})) - if values: + elif values: marginal_result_set = _generate_marginal_results( table, data, @@ -236,12 +239,15 @@ def _add_margins( return marginal_result_set result, margin_keys, row_margin = marginal_result_set else: + # no values, and table is a DataFrame + assert isinstance(table, ABCDataFrame) marginal_result_set = _generate_marginal_results_without_values( table, data, rows, cols, aggfunc, observed, margins_name ) if not isinstance(marginal_result_set, tuple): return marginal_result_set result, margin_keys, row_margin = marginal_result_set + row_margin = row_margin.reindex(result.columns, fill_value=fill_value) # populate grand margin for k in margin_keys: @@ -365,7 +371,7 @@ def _all_key(key): def _generate_marginal_results_without_values( - table, data, rows, cols, aggfunc, observed, margins_name: str = "All" + table: "DataFrame", data, rows, cols, aggfunc, observed, margins_name: str = "All" ): if len(cols) > 0: # need to "interleave" the margins From 6c70dcb242e894c93e9cd528ad771af0ae6ddcd5 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 14 Nov 2019 17:14:15 -0800 Subject: [PATCH 06/10] types --- pandas/core/reshape/pivot.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index a3048903df473..d08d842d64bf9 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -424,7 +424,7 @@ def _convert_by(by): @Substitution("\ndata : DataFrame") @Appender(_shared_docs["pivot"], indents=1) -def pivot(data, index=None, columns=None, values=None): +def pivot(data: "DataFrame", index=None, columns=None, values=None): if values is None: cols = [columns] if index is None else [index, columns] append = index is None @@ -454,8 +454,8 @@ def crosstab( colnames=None, aggfunc=None, margins=False, - margins_name="All", - dropna=True, + margins_name: str = "All", + dropna: bool = True, normalize=False, ): """ @@ -561,7 +561,7 @@ def crosstab( common_idx = _get_objs_combined_axis(index + columns, intersect=True, sort=False) - data = {} + data = {} # type: dict data.update(zip(rownames, index)) data.update(zip(colnames, columns)) From 3c7e76314c35003af67e9ddc730d25ea9191a87e Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 14 Nov 2019 17:22:14 -0800 Subject: [PATCH 07/10] types --- pandas/core/reshape/merge.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py index fc9faba8af827..61217f6e41d55 100644 --- a/pandas/core/reshape/merge.py +++ b/pandas/core/reshape/merge.py @@ -313,7 +313,7 @@ def merge_asof( suffixes=("_x", "_y"), tolerance=None, allow_exact_matches: bool = True, - direction="backward", + direction: str = "backward", ): """ Perform an asof merge. This is similar to a left-join except that we @@ -1489,12 +1489,12 @@ def get_result(self): return result -def _asof_function(direction): +def _asof_function(direction: str): name = "asof_join_{dir}".format(dir=direction) return getattr(libjoin, name, None) -def _asof_by_function(direction): +def _asof_by_function(direction: str): name = "asof_join_{dir}_on_X_by_Y".format(dir=direction) return getattr(libjoin, name, None) @@ -1538,7 +1538,7 @@ def __init__( how: str = "asof", tolerance=None, allow_exact_matches: bool = True, - direction="backward", + direction: str = "backward", ): self.by = by From 18a205e6a9caf5c50038845ff41697bae62087e0 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sat, 16 Nov 2019 19:24:22 -0800 Subject: [PATCH 08/10] suggested annotations --- pandas/core/reshape/concat.py | 3 ++- pandas/core/reshape/melt.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 4ce689eea6d3d..076868f937f02 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -2,6 +2,7 @@ concat routines """ +from typing import List import warnings import numpy as np @@ -537,7 +538,7 @@ def _get_concat_axis(self) -> Index: idx = ibase.default_index(len(self.objs)) return idx elif self.keys is None: - names = [None] * len(self.objs) # type: list + names = [None] * len(self.objs) # type: List num = 0 has_names = False for i, x in enumerate(self.objs): diff --git a/pandas/core/reshape/melt.py b/pandas/core/reshape/melt.py index 189d3d578565a..4cba52c5cd651 100644 --- a/pandas/core/reshape/melt.py +++ b/pandas/core/reshape/melt.py @@ -416,7 +416,7 @@ def wide_to_long(df: DataFrame, stubnames, i, j, sep: str = "", suffix: str = r" two 2.9 """ - def get_var_names(df, stub: str, sep: str, suffix) -> List[str]: + def get_var_names(df, stub: str, sep: str, suffix: str) -> List[str]: regex = r"^{stub}{sep}{suffix}$".format( stub=re.escape(stub), sep=re.escape(sep), suffix=suffix ) From 751ec83de8ae5e5566dba9361dafcc56762d2a26 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sat, 16 Nov 2019 19:26:20 -0800 Subject: [PATCH 09/10] use nlevels --- pandas/core/reshape/merge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py index 61217f6e41d55..4d838db6c95f6 100644 --- a/pandas/core/reshape/merge.py +++ b/pandas/core/reshape/merge.py @@ -1780,7 +1780,7 @@ def _get_multiindex_indexer(join_keys, index: MultiIndex, sort: bool): # left & right join labels and num. of levels at each location mapped = ( _factorize_keys(index.levels[n], join_keys[n], sort=sort) - for n in range(len(index.levels)) + for n in range(index.nlevels) ) zipped = zip(*mapped) rcodes, lcodes, shape = [list(x) for x in zipped] From 4895d19e04309d576f133c4cef11570f87c5dcd6 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 17 Nov 2019 07:42:55 -0800 Subject: [PATCH 10/10] new typing syntax --- pandas/core/reshape/concat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 076868f937f02..c2322ae626cfd 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -538,7 +538,7 @@ def _get_concat_axis(self) -> Index: idx = ibase.default_index(len(self.objs)) return idx elif self.keys is None: - names = [None] * len(self.objs) # type: List + names: List = [None] * len(self.objs) num = 0 has_names = False for i, x in enumerate(self.objs):