|
21 | 21 | is_scalar,
|
22 | 22 | is_string_like,
|
23 | 23 | )
|
24 |
| -from pandas.core.dtypes.generic import ABCIndexClass, ABCMultiIndex, ABCSeries |
| 24 | +from pandas.core.dtypes.generic import ( |
| 25 | + ABCDataFrame, |
| 26 | + ABCIndexClass, |
| 27 | + ABCMultiIndex, |
| 28 | + ABCSeries, |
| 29 | +) |
25 | 30 | from pandas.core.dtypes.missing import isna
|
26 | 31 |
|
27 | 32 | from pandas.core.algorithms import take_1d
|
@@ -2061,130 +2066,64 @@ def cons_row(x):
|
2061 | 2066 | cons = self._orig._constructor
|
2062 | 2067 | return cons(result, name=name, index=index)
|
2063 | 2068 |
|
2064 |
| - def _get_series_list(self, others, ignore_index=False): |
| 2069 | + def _get_series_list(self, others): |
2065 | 2070 | """
|
2066 | 2071 | Auxiliary function for :meth:`str.cat`. Turn potentially mixed input
|
2067 | 2072 | into a list of Series (elements without an index must match the length
|
2068 | 2073 | of the calling Series/Index).
|
2069 | 2074 |
|
2070 | 2075 | Parameters
|
2071 | 2076 | ----------
|
2072 |
| - others : Series, Index, DataFrame, np.ndarray, list-like or list-like |
2073 |
| - of objects that are Series, Index or np.ndarray (1-dim) |
2074 |
| - ignore_index : boolean, default False |
2075 |
| - Determines whether to forcefully align others with index of caller |
| 2077 | + others : Series, DataFrame, np.ndarray, list-like or list-like of |
| 2078 | + objects that are either Series, Index or np.ndarray (1-dim) |
2076 | 2079 |
|
2077 | 2080 | Returns
|
2078 | 2081 | -------
|
2079 |
| - tuple : (others transformed into list of Series, |
2080 |
| - boolean whether FutureWarning should be raised) |
| 2082 | + list : others transformed into list of Series |
2081 | 2083 | """
|
2082 |
| - |
2083 |
| - # Once str.cat defaults to alignment, this function can be simplified; |
2084 |
| - # will not need `ignore_index` and the second boolean output anymore |
2085 |
| - |
2086 | 2084 | from pandas import Series, DataFrame
|
2087 | 2085 |
|
2088 | 2086 | # self._orig is either Series or Index
|
2089 | 2087 | idx = self._orig if isinstance(self._orig, ABCIndexClass) else self._orig.index
|
2090 | 2088 |
|
2091 |
| - err_msg = ( |
2092 |
| - "others must be Series, Index, DataFrame, np.ndarray or " |
2093 |
| - "list-like (either containing only strings or containing " |
2094 |
| - "only objects of type Series/Index/list-like/np.ndarray)" |
2095 |
| - ) |
2096 |
| - |
2097 | 2089 | # Generally speaking, all objects without an index inherit the index
|
2098 | 2090 | # `idx` of the calling Series/Index - i.e. must have matching length.
|
2099 |
| - # Objects with an index (i.e. Series/Index/DataFrame) keep their own |
2100 |
| - # index, *unless* ignore_index is set to True. |
| 2091 | + # Objects with an index (i.e. Series/Index/DataFrame) keep their own. |
2101 | 2092 | if isinstance(others, ABCSeries):
|
2102 |
| - warn = not others.index.equals(idx) |
2103 |
| - # only reconstruct Series when absolutely necessary |
2104 |
| - los = [ |
2105 |
| - Series(others.values, index=idx) if ignore_index and warn else others |
2106 |
| - ] |
2107 |
| - return (los, warn) |
| 2093 | + return [others] |
2108 | 2094 | elif isinstance(others, ABCIndexClass):
|
2109 |
| - warn = not others.equals(idx) |
2110 |
| - los = [Series(others.values, index=(idx if ignore_index else others))] |
2111 |
| - return (los, warn) |
2112 |
| - elif isinstance(others, DataFrame): |
2113 |
| - warn = not others.index.equals(idx) |
2114 |
| - if ignore_index and warn: |
2115 |
| - # without copy, this could change "others" |
2116 |
| - # that was passed to str.cat |
2117 |
| - others = others.copy() |
2118 |
| - others.index = idx |
2119 |
| - return ([others[x] for x in others], warn) |
| 2095 | + return [Series(others.values, index=others)] |
| 2096 | + elif isinstance(others, ABCDataFrame): |
| 2097 | + return [others[x] for x in others] |
2120 | 2098 | elif isinstance(others, np.ndarray) and others.ndim == 2:
|
2121 | 2099 | others = DataFrame(others, index=idx)
|
2122 |
| - return ([others[x] for x in others], False) |
| 2100 | + return [others[x] for x in others] |
2123 | 2101 | elif is_list_like(others, allow_sets=False):
|
2124 | 2102 | others = list(others) # ensure iterators do not get read twice etc
|
2125 | 2103 |
|
2126 | 2104 | # in case of list-like `others`, all elements must be
|
2127 |
| - # either one-dimensional list-likes or scalars |
2128 |
| - if all(is_list_like(x, allow_sets=False) for x in others): |
| 2105 | + # either Series/Index/np.ndarray (1-dim)... |
| 2106 | + if all( |
| 2107 | + isinstance(x, (ABCSeries, ABCIndexClass)) |
| 2108 | + or (isinstance(x, np.ndarray) and x.ndim == 1) |
| 2109 | + for x in others |
| 2110 | + ): |
2129 | 2111 | los = []
|
2130 |
| - join_warn = False |
2131 |
| - depr_warn = False |
2132 |
| - # iterate through list and append list of series for each |
2133 |
| - # element (which we check to be one-dimensional and non-nested) |
2134 |
| - while others: |
2135 |
| - nxt = others.pop(0) # nxt is guaranteed list-like by above |
2136 |
| - |
2137 |
| - # GH 21950 - DeprecationWarning |
2138 |
| - # only allowing Series/Index/np.ndarray[1-dim] will greatly |
2139 |
| - # simply this function post-deprecation. |
2140 |
| - if not ( |
2141 |
| - isinstance(nxt, (Series, ABCIndexClass)) |
2142 |
| - or (isinstance(nxt, np.ndarray) and nxt.ndim == 1) |
2143 |
| - ): |
2144 |
| - depr_warn = True |
2145 |
| - |
2146 |
| - if not isinstance( |
2147 |
| - nxt, (DataFrame, Series, ABCIndexClass, np.ndarray) |
2148 |
| - ): |
2149 |
| - # safety for non-persistent list-likes (e.g. iterators) |
2150 |
| - # do not map indexed/typed objects; info needed below |
2151 |
| - nxt = list(nxt) |
2152 |
| - |
2153 |
| - # known types for which we can avoid deep inspection |
2154 |
| - no_deep = ( |
2155 |
| - isinstance(nxt, np.ndarray) and nxt.ndim == 1 |
2156 |
| - ) or isinstance(nxt, (Series, ABCIndexClass)) |
2157 |
| - # nested list-likes are forbidden: |
2158 |
| - # -> elements of nxt must not be list-like |
2159 |
| - is_legal = (no_deep and nxt.dtype == object) or all( |
2160 |
| - not is_list_like(x) for x in nxt |
2161 |
| - ) |
2162 |
| - |
2163 |
| - # DataFrame is false positive of is_legal |
2164 |
| - # because "x in df" returns column names |
2165 |
| - if not is_legal or isinstance(nxt, DataFrame): |
2166 |
| - raise TypeError(err_msg) |
2167 |
| - |
2168 |
| - nxt, wnx = self._get_series_list(nxt, ignore_index=ignore_index) |
2169 |
| - los = los + nxt |
2170 |
| - join_warn = join_warn or wnx |
2171 |
| - |
2172 |
| - if depr_warn: |
2173 |
| - warnings.warn( |
2174 |
| - "list-likes other than Series, Index, or " |
2175 |
| - "np.ndarray WITHIN another list-like are " |
2176 |
| - "deprecated and will be removed in a future " |
2177 |
| - "version.", |
2178 |
| - FutureWarning, |
2179 |
| - stacklevel=4, |
2180 |
| - ) |
2181 |
| - return (los, join_warn) |
| 2112 | + while others: # iterate through list and append each element |
| 2113 | + los = los + self._get_series_list(others.pop(0)) |
| 2114 | + return los |
| 2115 | + # ... or just strings |
2182 | 2116 | elif all(not is_list_like(x) for x in others):
|
2183 |
| - return ([Series(others, index=idx)], False) |
2184 |
| - raise TypeError(err_msg) |
| 2117 | + return [Series(others, index=idx)] |
| 2118 | + raise TypeError( |
| 2119 | + "others must be Series, Index, DataFrame, np.ndarrary " |
| 2120 | + "or list-like (either containing only strings or " |
| 2121 | + "containing only objects of type Series/Index/" |
| 2122 | + "np.ndarray[1-dim])" |
| 2123 | + ) |
2185 | 2124 |
|
2186 | 2125 | @forbid_nonstring_types(["bytes", "mixed", "mixed-integer"])
|
2187 |
| - def cat(self, others=None, sep=None, na_rep=None, join=None): |
| 2126 | + def cat(self, others=None, sep=None, na_rep=None, join="left"): |
2188 | 2127 | """
|
2189 | 2128 | Concatenate strings in the Series/Index with given separator.
|
2190 | 2129 |
|
@@ -2218,16 +2157,15 @@ def cat(self, others=None, sep=None, na_rep=None, join=None):
|
2218 | 2157 | - If `na_rep` is None, and `others` is not None, a row containing a
|
2219 | 2158 | missing value in any of the columns (before concatenation) will
|
2220 | 2159 | have a missing value in the result.
|
2221 |
| - join : {'left', 'right', 'outer', 'inner'}, default None |
| 2160 | + join : {'left', 'right', 'outer', 'inner'}, default 'left' |
2222 | 2161 | Determines the join-style between the calling Series/Index and any
|
2223 | 2162 | Series/Index/DataFrame in `others` (objects without an index need
|
2224 |
| - to match the length of the calling Series/Index). If None, |
2225 |
| - alignment is disabled, but this option will be removed in a future |
2226 |
| - version of pandas and replaced with a default of `'left'`. To |
2227 |
| - disable alignment, use `.values` on any Series/Index/DataFrame in |
2228 |
| - `others`. |
| 2163 | + to match the length of the calling Series/Index). To disable |
| 2164 | + alignment, use `.values` on any Series/Index/DataFrame in `others`. |
2229 | 2165 |
|
2230 | 2166 | .. versionadded:: 0.23.0
|
| 2167 | + .. versionchanged:: 1.0.0 |
| 2168 | + Changed default of `join` from None to `'left'`. |
2231 | 2169 |
|
2232 | 2170 | Returns
|
2233 | 2171 | -------
|
@@ -2343,39 +2281,14 @@ def cat(self, others=None, sep=None, na_rep=None, join=None):
|
2343 | 2281 |
|
2344 | 2282 | try:
|
2345 | 2283 | # turn anything in "others" into lists of Series
|
2346 |
| - others, warn = self._get_series_list(others, ignore_index=(join is None)) |
| 2284 | + others = self._get_series_list(others) |
2347 | 2285 | except ValueError: # do not catch TypeError raised by _get_series_list
|
2348 |
| - if join is None: |
2349 |
| - raise ValueError( |
2350 |
| - "All arrays must be same length, except " |
2351 |
| - "those having an index if `join` is not None" |
2352 |
| - ) |
2353 |
| - else: |
2354 |
| - raise ValueError( |
2355 |
| - "If `others` contains arrays or lists (or " |
2356 |
| - "other list-likes without an index), these " |
2357 |
| - "must all be of the same length as the " |
2358 |
| - "calling Series/Index." |
2359 |
| - ) |
2360 |
| - |
2361 |
| - if join is None and warn: |
2362 |
| - warnings.warn( |
2363 |
| - "A future version of pandas will perform index " |
2364 |
| - "alignment when `others` is a Series/Index/" |
2365 |
| - "DataFrame (or a list-like containing one). To " |
2366 |
| - "disable alignment (the behavior before v.0.23) and " |
2367 |
| - "silence this warning, use `.values` on any Series/" |
2368 |
| - "Index/DataFrame in `others`. To enable alignment " |
2369 |
| - "and silence this warning, pass `join='left'|" |
2370 |
| - "'outer'|'inner'|'right'`. The future default will " |
2371 |
| - "be `join='left'`.", |
2372 |
| - FutureWarning, |
2373 |
| - stacklevel=3, |
| 2286 | + raise ValueError( |
| 2287 | + "If `others` contains arrays or lists (or other " |
| 2288 | + "list-likes without an index), these must all be " |
| 2289 | + "of the same length as the calling Series/Index." |
2374 | 2290 | )
|
2375 | 2291 |
|
2376 |
| - # if join is None, _get_series_list already force-aligned indexes |
2377 |
| - join = "left" if join is None else join |
2378 |
| - |
2379 | 2292 | # align if required
|
2380 | 2293 | if any(not data.index.equals(x.index) for x in others):
|
2381 | 2294 | # Need to add keys for uniqueness in case of duplicate columns
|
|
0 commit comments