2
2
import numpy as np
3
3
4
4
from pandas .compat import zip
5
- from pandas .core .dtypes .generic import ABCSeries , ABCIndex , ABCMultiIndex
5
+ from pandas .core .dtypes .generic import ABCSeries , ABCIndexClass , ABCMultiIndex
6
6
from pandas .core .dtypes .missing import isna
7
7
from pandas .core .dtypes .common import (
8
8
ensure_object ,
@@ -942,7 +942,7 @@ def str_extractall(arr, pat, flags=0):
942
942
if regex .groups == 0 :
943
943
raise ValueError ("pattern contains no capture groups" )
944
944
945
- if isinstance (arr , ABCIndex ):
945
+ if isinstance (arr , ABCIndexClass ):
946
946
arr = arr .to_series ().reset_index (drop = True )
947
947
948
948
names = dict (zip (regex .groupindex .values (), regex .groupindex .keys ()))
@@ -1757,8 +1757,8 @@ def forbid_nonstring_types(forbidden, name=None):
1757
1757
make it explicit which (inferred) types are disallowed by the method.
1758
1758
1759
1759
:meth:`StringMethods.__init__` allows the *union* of types its different
1760
- methods allow (after skipping NaNs; see :meth:`StringMethods._validate`):
1761
- ['string', 'unicode', 'empty', 'bytes', 'mixed', 'mixed-integer'].
1760
+ methods allow (after skipping NaNs; see :meth:`StringMethods._validate`),
1761
+ namely: ['string', 'unicode', 'empty', 'bytes', 'mixed', 'mixed-integer'].
1762
1762
1763
1763
The default string types ['string', 'unicode', 'empty'] are allowed for all
1764
1764
methods. For the additional types ['bytes', 'mixed', 'mixed-integer'], each
@@ -1783,7 +1783,7 @@ def forbid_nonstring_types(forbidden, name=None):
1783
1783
1784
1784
Raises
1785
1785
------
1786
- AttributeError
1786
+ TypeError
1787
1787
If the inferred type of the underlying data is in `forbidden`.
1788
1788
"""
1789
1789
@@ -1800,11 +1800,11 @@ def _forbid_nonstring_types(func):
1800
1800
1801
1801
@wraps (func )
1802
1802
def wrapper (self , * args , ** kwargs ):
1803
- if self ._inferred_type not in allowed_types :
1804
- msg = (" Cannot use .str.{name} with values of inferred type "
1805
- " {inf_type!r}." .format (name = func_name ,
1806
- inf_type = self ._inferred_type ))
1807
- raise AttributeError (msg )
1803
+ if self ._inferred_dtype not in allowed_types :
1804
+ msg = (' Cannot use .str.{name} with values of inferred dtype '
1805
+ ' {inf_type!r}.' .format (name = func_name ,
1806
+ inf_type = self ._inferred_dtype ))
1807
+ raise TypeError (msg )
1808
1808
return func (self , * args , ** kwargs )
1809
1809
wrapper .__name__ = func_name
1810
1810
return wrapper
@@ -1877,7 +1877,7 @@ class StringMethods(NoNewAttributesMixin):
1877
1877
"""
1878
1878
1879
1879
def __init__ (self , data ):
1880
- self ._inferred_type = self ._validate (data )
1880
+ self ._inferred_dtype = self ._validate (data )
1881
1881
self ._is_categorical = is_categorical_dtype (data )
1882
1882
1883
1883
# .values.categories works for both Series/Index
@@ -1899,10 +1899,10 @@ def _validate(data):
1899
1899
values = getattr (data , 'values' , data ) # Series / Index
1900
1900
values = getattr (values , 'categories' , values ) # categorical / normal
1901
1901
1902
- # missing values obfuscates type inference -> skip
1903
- inferred_type = lib .infer_dtype (values , skipna = True )
1902
+ # missing values obfuscate type inference -> skip
1903
+ inferred_dtype = lib .infer_dtype (values , skipna = True )
1904
1904
1905
- if inferred_type not in allowed_types :
1905
+ if inferred_dtype not in allowed_types :
1906
1906
# this is a "first line of defence" and just checks that the type
1907
1907
# is in the *union* of the allowed types over all methods below;
1908
1908
# this restriction is then refined on a per-method basis using the
@@ -1913,7 +1913,7 @@ def _validate(data):
1913
1913
# have a str dtype (GH 9343 / 13877)
1914
1914
raise AttributeError ("Can only use .str accessor with string "
1915
1915
"values!" )
1916
- return inferred_type
1916
+ return inferred_dtype
1917
1917
1918
1918
def __getitem__ (self , key ):
1919
1919
if isinstance (key , slice ):
@@ -1932,15 +1932,16 @@ def __iter__(self):
1932
1932
def _wrap_result (self , result , use_codes = True ,
1933
1933
name = None , expand = None ):
1934
1934
1935
- from pandas . core . index import Index , MultiIndex
1935
+ from pandas import Index , Series , MultiIndex
1936
1936
1937
1937
# for category, we do the stuff on the categories, so blow it up
1938
1938
# to the full series again
1939
1939
# But for some operations, we have to do the stuff on the full values,
1940
1940
# so make it possible to skip this step as the method already did this
1941
1941
# before the transformation...
1942
1942
if use_codes and self ._is_categorical :
1943
- result = take_1d (result , self ._orig .cat .codes )
1943
+ # if self._orig is a CategoricalIndex, there is no .cat-accessor
1944
+ result = take_1d (result , Series (self ._orig ).cat .codes )
1944
1945
1945
1946
if not hasattr (result , 'ndim' ) or not hasattr (result , 'dtype' ):
1946
1947
return result
0 commit comments