From 91ab671350128cc390e1b11dba3cf593dc3231bc Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 19:47:42 -0500 Subject: [PATCH 01/18] fix Summary does not end with a period error --- pandas/core/accessor.py | 2 +- pandas/core/arrays/categorical.py | 6 ++--- pandas/core/arrays/datetimes.py | 18 +++++++-------- pandas/core/base.py | 6 ++--- pandas/core/dtypes/dtypes.py | 2 +- pandas/core/generic.py | 36 +++++++++++++++--------------- pandas/core/indexes/accessors.py | 2 +- pandas/plotting/_core.py | 18 +++++++-------- scripts/tmp.xlsx | Bin 0 -> 5418 bytes 9 files changed, 45 insertions(+), 45 deletions(-) create mode 100644 scripts/tmp.xlsx diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index fa1dc751c17da..1beb097f58bdf 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -59,7 +59,7 @@ def _delegate_method(self, name, *args, **kwargs): def _add_delegate_accessors(cls, delegate, accessors, typ, overwrite=False): """ - add accessors to cls from the delegate class + add accessors to cls from the delegate class. Parameters ---------- diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 6e96fc75daec9..2cf9af16f0fdb 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -477,7 +477,7 @@ def categories(self, categories): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self.dtype.ordered @@ -782,7 +782,7 @@ def set_ordered(self, value, inplace=False): def as_ordered(self, inplace=False): """ - Sets the Categorical to be ordered + Sets the Categorical to be ordered. Parameters ---------- @@ -795,7 +795,7 @@ def as_ordered(self, inplace=False): def as_unordered(self, inplace=False): """ - Sets the Categorical to be unordered + Sets the Categorical to be unordered. Parameters ---------- diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index b74ede4547249..d176e5d244cd1 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1065,19 +1065,19 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', "\n The year of the datetime\n") + year = _field_accessor('year', 'Y', "\n The year of the datetime.\n") month = _field_accessor('month', 'M', - "\n The month as January=1, December=12 \n") - day = _field_accessor('day', 'D', "\nThe days of the datetime\n") - hour = _field_accessor('hour', 'h', "\nThe hours of the datetime\n") - minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime\n") - second = _field_accessor('second', 's', "\nThe seconds of the datetime\n") + "\n The month as January=1, December=12. \n") + day = _field_accessor('day', 'D', "\nThe days of the datetime.\n") + hour = _field_accessor('hour', 'h', "\nThe hours of the datetime.\n") + minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime.\n") + second = _field_accessor('second', 's', "\nThe seconds of the datetime.\n") microsecond = _field_accessor('microsecond', 'us', - "\nThe microseconds of the datetime\n") + "\nThe microseconds of the datetime.\n") nanosecond = _field_accessor('nanosecond', 'ns', - "\nThe nanoseconds of the datetime\n") + "\nThe nanoseconds of the datetime.\n") weekofyear = _field_accessor('weekofyear', 'woy', - "\nThe week ordinal of the year\n") + "\nThe week ordinal of the year.\n") week = weekofyear _dayofweek_doc = """ The day of the week with Monday=0, Sunday=6. diff --git a/pandas/core/base.py b/pandas/core/base.py index 1d2a0a2544dbc..161bf8fbf3482 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -1244,7 +1244,7 @@ def nunique(self, dropna=True): @property def is_unique(self): """ - Return boolean if values in the object are unique + Return boolean if values in the object are unique. Returns ------- @@ -1256,7 +1256,7 @@ def is_unique(self): def is_monotonic(self): """ Return boolean if values in the object are - monotonic_increasing + monotonic_increasing. .. versionadded:: 0.19.0 @@ -1273,7 +1273,7 @@ def is_monotonic(self): def is_monotonic_decreasing(self): """ Return boolean if values in the object are - monotonic_decreasing + monotonic_decreasing. .. versionadded:: 0.19.0 diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 0db76cd934d19..24407850d44a8 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -463,7 +463,7 @@ def categories(self): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self._ordered diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 1e26c3f45f660..1a2c04cd1a267 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -671,7 +671,7 @@ def transpose(self, *args, **kwargs): def swapaxes(self, axis1, axis2, copy=True): """ - Interchange axes and swap values axes appropriately + Interchange axes and swap values axes appropriately. Returns ------- @@ -1907,7 +1907,7 @@ def __array_wrap__(self, result, context=None): def to_dense(self): """ - Return dense representation of NDFrame (as opposed to sparse) + Return dense representation of NDFrame (as opposed to sparse). """ # compat return self @@ -3597,7 +3597,7 @@ class animal locomotion def select(self, crit, axis=0): """ - Return data corresponding to axis labels matching criteria + Return data corresponding to axis labels matching criteria. .. deprecated:: 0.21.0 Use df.loc[df.index.map(crit)] to select via labels @@ -4841,7 +4841,7 @@ def sample(self, n=None, frac=None, replace=False, weights=None, return self.take(locs, axis=axis, is_copy=False) _shared_docs['pipe'] = (r""" - Apply func(self, \*args, \*\*kwargs) + Apply func(self, \*args, \*\*kwargs). Parameters ---------- @@ -5533,7 +5533,7 @@ def as_blocks(self, copy=True): @property def blocks(self): """ - Internal property, property synonym for as_blocks() + Internal property, property synonym for as_blocks(). .. deprecated:: 0.21.0 """ @@ -5918,7 +5918,7 @@ def infer_objects(self): def fillna(self, value=None, method=None, axis=None, inplace=False, limit=None, downcast=None): """ - Fill NA/NaN values using the specified method + Fill NA/NaN values using the specified method. Parameters ---------- @@ -6103,14 +6103,14 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') ` + Synonym for :meth:`DataFrame.fillna(method='ffill') `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') ` + Synonym for :meth:`DataFrame.fillna(method='bfill') `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) @@ -8251,7 +8251,7 @@ def rank(self, axis=0, method='average', numeric_only=None, na_option='keep', ascending=True, pct=False): """ Compute numerical data ranks (1 through n) along axis. Equal values are - assigned a rank that is the average of the ranks of those values + assigned a rank that is the average of the ranks of those values. Parameters ---------- @@ -8313,7 +8313,7 @@ def ranker(data): _shared_docs['align'] = (""" Align two objects on their axes with the - specified join method for each axis Index + specified join method for each axis Index. Parameters ---------- @@ -9902,7 +9902,7 @@ def _add_numeric_operations(cls): @Substitution(outname='mad', desc="Return the mean absolute deviation of the values " - "for the requested axis", + "for the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9944,7 +9944,7 @@ def mad(self, axis=None, skipna=None, level=None): @Substitution(outname='compounded', desc="Return the compound percentage of the values for " - "the requested axis", name1=name, name2=name2, + "the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9974,31 +9974,31 @@ def compound(self, axis=None, skipna=None, level=None): cls.sum = _make_min_count_stat_function( cls, 'sum', name, name2, axis_descr, - 'Return the sum of the values for the requested axis', + 'Return the sum of the values for the requested axis.', nanops.nansum, _sum_examples) cls.mean = _make_stat_function( cls, 'mean', name, name2, axis_descr, - 'Return the mean of the values for the requested axis', + 'Return the mean of the values for the requested axis.', nanops.nanmean) cls.skew = _make_stat_function( cls, 'skew', name, name2, axis_descr, - 'Return unbiased skew over requested axis\nNormalized by N-1', + 'Return unbiased skew over requested axis\nNormalized by N-1.', nanops.nanskew) cls.kurt = _make_stat_function( cls, 'kurt', name, name2, axis_descr, "Return unbiased kurtosis over requested axis using Fisher's " "definition of\nkurtosis (kurtosis of normal == 0.0). Normalized " - "by N-1", + "by N-1.", nanops.nankurt) cls.kurtosis = cls.kurt cls.prod = _make_min_count_stat_function( cls, 'prod', name, name2, axis_descr, - 'Return the product of the values for the requested axis', + 'Return the product of the values for the requested axis.', nanops.nanprod, _prod_examples) cls.product = cls.prod cls.median = _make_stat_function( cls, 'median', name, name2, axis_descr, - 'Return the median of the values for the requested axis', + 'Return the median of the values for the requested axis.', nanops.nanmedian) cls.max = _make_stat_function( cls, 'max', name, name2, axis_descr, diff --git a/pandas/core/indexes/accessors.py b/pandas/core/indexes/accessors.py index 82b6b22be4a79..ecc96ca1ecc94 100644 --- a/pandas/core/indexes/accessors.py +++ b/pandas/core/indexes/accessors.py @@ -130,7 +130,7 @@ class DatetimeProperties(Properties): def to_pydatetime(self): """ - Return the data as an array of native Python datetime objects + Return the data as an array of native Python datetime objects. Timezone information is retained if present. diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index ec6743e205848..52d40f84cb1d9 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -2417,7 +2417,7 @@ def hist_series(self, by=None, ax=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, figsize=None, bins=10, **kwds): """ - Draw histogram of the input series using matplotlib + Draw histogram of the input series using matplotlib. Parameters ---------- @@ -2706,7 +2706,7 @@ def __call__(self, *args, **kwargs): class SeriesPlotMethods(BasePlotMethods): """ - Series plotting accessor and method + Series plotting accessor and method. Examples -------- @@ -2739,7 +2739,7 @@ def __call__(self, kind='line', ax=None, def line(self, **kwds): """ - Line plot + Line plot. Parameters ---------- @@ -2764,7 +2764,7 @@ def line(self, **kwds): def bar(self, **kwds): """ - Vertical bar plot + Vertical bar plot. Parameters ---------- @@ -2780,7 +2780,7 @@ def bar(self, **kwds): def barh(self, **kwds): """ - Horizontal bar plot + Horizontal bar plot. Parameters ---------- @@ -2796,7 +2796,7 @@ def barh(self, **kwds): def box(self, **kwds): """ - Boxplot + Boxplot. Parameters ---------- @@ -2812,7 +2812,7 @@ def box(self, **kwds): def hist(self, bins=10, **kwds): """ - Histogram + Histogram. Parameters ---------- @@ -2873,7 +2873,7 @@ def kde(self, bw_method=None, ind=None, **kwds): def area(self, **kwds): """ - Area plot + Area plot. Parameters ---------- @@ -2889,7 +2889,7 @@ def area(self, **kwds): def pie(self, **kwds): """ - Pie chart + Pie chart. Parameters ---------- diff --git a/scripts/tmp.xlsx b/scripts/tmp.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..030a0f83d63206d20e884777e6a90cc587791dbd GIT binary patch literal 5418 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 literal 0 HcmV?d00001 From b3668195d18bd4f4f55f6d9f58cb1b4645a4929d Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 19:57:49 -0500 Subject: [PATCH 02/18] fixed generic.py PEP8 - line too long issues --- pandas/core/generic.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 1a2c04cd1a267..1ea8ac55540a7 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6103,14 +6103,16 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') `. + Synonym for :meth:`DataFrame.fillna(method='ffill') + `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') `. + Synonym for :meth:`DataFrame.fillna(method='bfill') + `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) From 88d6664afaa5911055fd6bd0aac136813c13119c Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 19:59:21 -0500 Subject: [PATCH 03/18] fixed generic.py PEP8 - trailing whitespace issues --- pandas/core/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 1ea8ac55540a7..e52a0b60c610e 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6103,7 +6103,7 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') + Synonym for :meth:`DataFrame.fillna(method='ffill') `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, @@ -6111,7 +6111,7 @@ def ffill(self, axis=None, inplace=False, limit=None, downcast=None): def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') + Synonym for :meth:`DataFrame.fillna(method='bfill') `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, From ad50026108437989ba2b2035bba29718b32aeccd Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 21:35:25 -0500 Subject: [PATCH 04/18] fixed minor errors --- pandas/core/accessor.py | 2 +- pandas/core/arrays/categorical.py | 4 ++-- pandas/core/arrays/datetimes.py | 18 +++++++++--------- scripts/tmp.xlsx | Bin 5418 -> 0 bytes 4 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 scripts/tmp.xlsx diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index 1beb097f58bdf..93b4ce31a1e25 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -59,7 +59,7 @@ def _delegate_method(self, name, *args, **kwargs): def _add_delegate_accessors(cls, delegate, accessors, typ, overwrite=False): """ - add accessors to cls from the delegate class. + Add accessors to cls from the delegate class. Parameters ---------- diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 2cf9af16f0fdb..b2c580ac435db 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -782,7 +782,7 @@ def set_ordered(self, value, inplace=False): def as_ordered(self, inplace=False): """ - Sets the Categorical to be ordered. + Set the Categorical to be ordered. Parameters ---------- @@ -795,7 +795,7 @@ def as_ordered(self, inplace=False): def as_unordered(self, inplace=False): """ - Sets the Categorical to be unordered. + Set the Categorical to be unordered. Parameters ---------- diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index d176e5d244cd1..4b4c49f0f0617 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1065,19 +1065,19 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', "\n The year of the datetime.\n") + year = _field_accessor('year', 'Y', " The year of the datetime.") month = _field_accessor('month', 'M', - "\n The month as January=1, December=12. \n") - day = _field_accessor('day', 'D', "\nThe days of the datetime.\n") - hour = _field_accessor('hour', 'h', "\nThe hours of the datetime.\n") - minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime.\n") - second = _field_accessor('second', 's', "\nThe seconds of the datetime.\n") + " The month as January=1, December=12. ") + day = _field_accessor('day', 'D', "The days of the datetime.") + hour = _field_accessor('hour', 'h', "The hours of the datetime.") + minute = _field_accessor('minute', 'm', "The minutes of the datetime.") + second = _field_accessor('second', 's', "The seconds of the datetime.") microsecond = _field_accessor('microsecond', 'us', - "\nThe microseconds of the datetime.\n") + "The microseconds of the datetime.") nanosecond = _field_accessor('nanosecond', 'ns', - "\nThe nanoseconds of the datetime.\n") + "The nanoseconds of the datetime.") weekofyear = _field_accessor('weekofyear', 'woy', - "\nThe week ordinal of the year.\n") + "The week ordinal of the year.") week = weekofyear _dayofweek_doc = """ The day of the week with Monday=0, Sunday=6. diff --git a/scripts/tmp.xlsx b/scripts/tmp.xlsx deleted file mode 100644 index 030a0f83d63206d20e884777e6a90cc587791dbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5418 zcmZ`-2Q*ym79A~&PG)qXL?69Hh)#4fdW{5Qj52x%B6^J)MDHRZNJ55?sL^{OLxC8PyUnR6==!t^=X?V+&|(k#aeU3gx0Do%KQsNv=i}|z+_3kF&0AOTl!L;~(<5WjwtMZB{dFIb@*4~hW)$r-V)BpJ?ENOx z5oYQLF3g6m&%?oCwayht6=YsL+Ys6B%*Vo;DevK!XtrVBj!s(2bxR@1F*1EqK-h&C zs!}R7!d!7V%vlwI{!x~224`+fTv>Qs_ke$>+Ud4hwRLz*@RCO=s^Uwkb!3XQd4e$uTNwmCJe|4hkohrAd=`)yD>6pT%q8*wg?%M;9df~32y zI$>&u4UWQxcjt|@@5z=LHEtjsddbZdzvh9Oc{t*i={JFYHSfy~)IuniMnw+hgYDq~ zBnNCBD(9fJ?0sHW`qU7ccn1%LZtZGq?aO^5nfi!c7V}U1zBi{TgQbH+NmT7qG0cCG zo=d!USb`(_5{~$v9fIoxZ>Kw6a0eqFFC+@#{gZk4urg`8D0SrgyK<5R%a5jfoLY_4 z@}X?(=n@LaM^jmGv$JtA(8uR8Z#y&BXykmmLsdD+j;<3#8kh5od}?3yH+NHh>F*r$ zm_$fErO1n{1LB-bYvrW=BX8Wgp5aD~QIe#MFf!)W6PD`iW4!wvLdEa(=`BpxRtQ3$ zeblroB9t<0NN6}mOR(h9EGN(*_T&^i@>Lb0;bM;!Kc6TWBsI|gnbfVu@{fMFgs2H{ z7cMCWcYCOpyN9>P9S@J63FW1>>931Ys~-fZFW&GqfHV15n# z7h`coO}EykWPHI_jS}9z_r=i-Q?I4h*^76o9XcTh#%r5`3ux}ZshPZUd&X3+^jEXW zz55{>+WE02dw86Ttq|^O5DQfhU2X}g(Bztq{bQcjNma$hT|x)GZjv+pr?X*P3d6fP zlydlH%D!w}N_RD_efB0s`quNQ3S^Fxzm+ynwlP)lotB=s`|Pc_^r8Hio`3yVq^ayO zf*l>XwG?Kc^K!heU7V=j(t@z9g$cuE+)|q^PE)qxG#bitMMCll(#1RDoj?RzxkFx@ zhO8a&bP+=xg(j@|@Gy!3Q1sQ_JJ|?poI_?o9(7eeA&5}x2guXD2VY@a5WGr{vD20p zeF0o(Tow%8W;OVc@ovuzDlC+owAR)j6GY1VpoAoGUEVFuw}jJp^-`B_5`||$L-FQm zzs4IOQuylua~@ogptyFY`R^jxyL-X^ zuF@b1x9uXZ_v3mF-iuXOzDQ+%4KC+25io(dXS^e<+(~k+53R4c%pUT-qWk+muw0Xu z>|BNP5z%tlD45eCk#=N;q#}p({&Tuj5VwM;khzPbu@e>B;CfT4RbN853*^g7zaF&l=KFyAZ zPotx<%>j%jf!a5Z%jTQaiEWJ1xI@F~Uv11G6?Z752R9CQ@`T+z;GI=PIPZ3v(K<&| z_|2zdGqC--#o={!AWPiF9U)hXGN{<~O0cJm@Y^HxUYUq6IXQ}PX^a$E#Eg!U-~$5b z`!#PRdYO8<1V-bX&AIhP7C@ZZ?Pbpo}Wt*g>wfGEI=o#l| zJD;Dv;oM|!RX9)0Qnt1BW@n}n<8!>Ho}E*BBw2?K!oJr&kZ!4!#XliO?$fkyeCR;C zjPk7;eD$+S`{H#rrWn3)lEiwiiZ)Y5JBY&iWU(dC-MeQ?fiW2GPyUhB5e&yT{%;Tg z02Kc|PJQmV!hfBk?~Lc-b496xv9>hdf|mvMoZ@O3Okc!#VWusA*)eZCHIsO zTPyZQ9DbrYXEWZEgp759PE?{nTC`>d)?$9{m#RI>rA)ELl6nOTG~95^V`XM zJd#4Y<4zu>(j`%0jyi<{U&v%7V%^Fl`FE!@?Sbq!_Gvh?`PpdZGC}EJh0o&Li!2>k zR1t}ExwKQ}S9I+n535qoVS*6KM-gcg9d?BS#FtvD6pB^pjwPwgZ6_bxNvsTqF7zy}*F3)GEc5%=zSLLIdZ}TjRumo4xS6BmxEh0 zTZM&J6Tl*wYgqpTJXFO4Wu-BNuxQ$-f+_V--$VA!^ye;Vhb@(bEhqLIer~2E$?SWA zshkK2H|Hpu+u&v`Gn3?!c_C)*-0{IM)V{%N4D9|bSWD+*YuMDrl{5V(R7K&N^MdCW zb_v4|4dWNM9b(A*cbDQ`x;{>DH~8Q8U)poiLN94rjiGs0P@}m%@v_`tb#|5XWNG9k zy7Eii)9%=P`mjWwQbw=J>VT` zIBT~b@AE;MAp*F*Z>5juG9my!?tj}PRkLKe!*t$78(i{n)t?z0WFPAHc)QB-S%>$N6kKnKw#OlObbMC* z)nN*-N-v?VgEuP#>{P<0lFH86sWkg|6P-IyXfCidhtS0@PRLf+4gM;5k4VpC`UhVp zl!mOQa#`_hz!~UWz}e#BeC?xX#RB;NpKsf|1oITR5!dJYu?pwwIR+yI1}*oG4s|4M ztsTwU_|~daaq6#4wL0C;1Pgs>-wW(uniTL7;FqMlYk-hNb(+^Z+99( z@#x4PQX?Ga?TQyDMHR$*xAIBd+*4I}j4t=1)C8QjBx0l~wNyZTTRUPLmtF;?nVvM> zyx+!sh2JNsnDU9nWAYVfRxE0S0V6KOPf}EU=!g|w^Ki6lQB8cN$wxAv3jtO(>|D?1 zV_}x+68o4U^D<6Xn@vB`*0aHwdNo-zF#s>+gPOOMuHf31-HKY*3+zjzwK}PKH_xKp zz?;OG`2|$O!q`&@Jx=`A#UIDb$IaO0`1^h)LN(KF z^c3Uc%a~l-w_ciTurA6^X(>74?t`>xls{f%iFg$s>E>&ASj1I+RSDg7x!Uj}^Vy1M zJAaI)7qAFo5lvfW-LBPY*(;~0Zz!rTx9f;dQnG*D9d6fDR6w!p`ptyTS2^KfTVp$u z*{pu15nv*1$=?w6{-~~Psm{k)kfJ(9GtyYjT!Y9Y*kyn1s>O=!!OQ>^y?sa#b5*%| z$zLb&mY>U2bu_pzm0-De_`M_p5KT19<6)F5C#C4hCfy_$3LJj;!^A)$RD`Ih|khnrPuPjWH}41B;hMA${1Z9%B_q;9Tyib|T&V%C9iVH=>5bl4@Zp)^C48E&=pg1dT) z2>-lS;k-wOD7g|A=RJx1$MYYB$?EaZ?%CJ<5oQ1no1{~6MgN`UNAG#9bBM=5#ElH;i^mv%+(yCe&+X3wR7 zl*2+_^bNgC!9-A>K|fN3e|T&)=5A}^-m_|~&yU`arHBgjkkV8m_tR6c4^pluEBDou z%{#^H2+NZ`J_lXa*wA}p*xV?yr6K|7$g+*;MAONQ@_fyaqC#}86OB=YKBnKY#g}E; z2Dm)@P)DWy{0&QXWEhv91)%Yz;{*FBk9<=$RIcm%Vds7;~jZD}S(wykC|vrdvT|58reA zV9l&{TrO`U*rRVkx-4_5MfBSmW{nG~gNG0L<+=a&R0>DZuMax(=kot%R2QRM9HRUk z0{}pWKE}z?e@FR;?~CAz!+_sla-5U?U!#GG5iUCK-x20<5ia`hi|C7%@HaXNrLC*gkLm2zv0uD{-+hX7~rCM{~f>zSEHZ#|3}MTgkF?%zoDU|zn~Wd-o*eHkBr{| t>~JHD|2jY}0xx#fZ=es(R^uM}|MVGDhX}_C06>cShTys~jrQlSe*r`gFoggB From d3d0bd013efd0a2f993a57a6f07ba599b00e27b6 Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 21:37:39 -0500 Subject: [PATCH 05/18] removed a few more \n --- pandas/core/arrays/datetimes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 4b4c49f0f0617..7401b2534a237 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -82,7 +82,7 @@ def f(self): return result f.__name__ = name - f.__doc__ = "\n{}\n".format(docstring) + f.__doc__ = "{}".format(docstring) return property(f) @@ -1119,7 +1119,7 @@ def date(self): weekday_name = _field_accessor( 'weekday_name', 'weekday_name', - "The name of day in a week (ex: Friday)\n\n.. deprecated:: 0.23.0") + "The name of day in a week (ex: Friday).. deprecated:: 0.23.0") dayofyear = _field_accessor('dayofyear', 'doy', "The ordinal day of the year.") From 97444fb8b7d1dedd0437ba995feceb2d61b15f6f Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 21:46:50 -0500 Subject: [PATCH 06/18] added back required \n --- pandas/core/arrays/datetimes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 7401b2534a237..9e8116bd15611 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1119,7 +1119,7 @@ def date(self): weekday_name = _field_accessor( 'weekday_name', 'weekday_name', - "The name of day in a week (ex: Friday).. deprecated:: 0.23.0") + "The name of day in a week (ex: Friday)\n\n.. deprecated:: 0.23.0") dayofyear = _field_accessor('dayofyear', 'doy', "The ordinal day of the year.") From dc0a303baaf9293965b9946b05d22414a0a7a8f2 Mon Sep 17 00:00:00 2001 From: Marc Garcia Date: Sun, 9 Dec 2018 21:53:53 -0500 Subject: [PATCH 07/18] Update pandas/core/arrays/datetimes.py Co-Authored-By: YuechengWu --- pandas/core/arrays/datetimes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 9e8116bd15611..7bacb951c1dca 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1065,7 +1065,7 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', " The year of the datetime.") + year = _field_accessor('year', 'Y', "The year of the datetime.") month = _field_accessor('month', 'M', " The month as January=1, December=12. ") day = _field_accessor('day', 'D', "The days of the datetime.") From 86398414357506cf49cb1260a0d3962894c2fccf Mon Sep 17 00:00:00 2001 From: Marc Garcia Date: Sun, 9 Dec 2018 21:54:09 -0500 Subject: [PATCH 08/18] Update pandas/core/arrays/datetimes.py Co-Authored-By: YuechengWu --- pandas/core/arrays/datetimes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 7bacb951c1dca..ab848bad93cc6 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1067,7 +1067,7 @@ def date(self): year = _field_accessor('year', 'Y', "The year of the datetime.") month = _field_accessor('month', 'M', - " The month as January=1, December=12. ") + "The month as January=1, December=12. ") day = _field_accessor('day', 'D', "The days of the datetime.") hour = _field_accessor('hour', 'h', "The hours of the datetime.") minute = _field_accessor('minute', 'm', "The minutes of the datetime.") From b052287c38a9919ecee94e3035d614cfc62cb60c Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 19:47:42 -0500 Subject: [PATCH 09/18] fix Summary does not end with a period error --- pandas/core/accessor.py | 2 +- pandas/core/arrays/categorical.py | 6 ++--- pandas/core/arrays/datetimes.py | 18 +++++++-------- pandas/core/base.py | 6 ++--- pandas/core/dtypes/dtypes.py | 2 +- pandas/core/generic.py | 36 +++++++++++++++--------------- pandas/core/indexes/accessors.py | 2 +- pandas/plotting/_core.py | 18 +++++++-------- scripts/tmp.xlsx | Bin 0 -> 5418 bytes 9 files changed, 45 insertions(+), 45 deletions(-) create mode 100644 scripts/tmp.xlsx diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index fa1dc751c17da..1beb097f58bdf 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -59,7 +59,7 @@ def _delegate_method(self, name, *args, **kwargs): def _add_delegate_accessors(cls, delegate, accessors, typ, overwrite=False): """ - add accessors to cls from the delegate class + add accessors to cls from the delegate class. Parameters ---------- diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index abadd64b441b4..c85c347b523d0 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -477,7 +477,7 @@ def categories(self, categories): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self.dtype.ordered @@ -782,7 +782,7 @@ def set_ordered(self, value, inplace=False): def as_ordered(self, inplace=False): """ - Sets the Categorical to be ordered + Sets the Categorical to be ordered. Parameters ---------- @@ -795,7 +795,7 @@ def as_ordered(self, inplace=False): def as_unordered(self, inplace=False): """ - Sets the Categorical to be unordered + Sets the Categorical to be unordered. Parameters ---------- diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 72ab400b41c0c..70b95d64608db 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1070,19 +1070,19 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', "\n The year of the datetime\n") + year = _field_accessor('year', 'Y', "\n The year of the datetime.\n") month = _field_accessor('month', 'M', - "\n The month as January=1, December=12 \n") - day = _field_accessor('day', 'D', "\nThe days of the datetime\n") - hour = _field_accessor('hour', 'h', "\nThe hours of the datetime\n") - minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime\n") - second = _field_accessor('second', 's', "\nThe seconds of the datetime\n") + "\n The month as January=1, December=12. \n") + day = _field_accessor('day', 'D', "\nThe days of the datetime.\n") + hour = _field_accessor('hour', 'h', "\nThe hours of the datetime.\n") + minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime.\n") + second = _field_accessor('second', 's', "\nThe seconds of the datetime.\n") microsecond = _field_accessor('microsecond', 'us', - "\nThe microseconds of the datetime\n") + "\nThe microseconds of the datetime.\n") nanosecond = _field_accessor('nanosecond', 'ns', - "\nThe nanoseconds of the datetime\n") + "\nThe nanoseconds of the datetime.\n") weekofyear = _field_accessor('weekofyear', 'woy', - "\nThe week ordinal of the year\n") + "\nThe week ordinal of the year.\n") week = weekofyear _dayofweek_doc = """ The day of the week with Monday=0, Sunday=6. diff --git a/pandas/core/base.py b/pandas/core/base.py index 1d2a0a2544dbc..161bf8fbf3482 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -1244,7 +1244,7 @@ def nunique(self, dropna=True): @property def is_unique(self): """ - Return boolean if values in the object are unique + Return boolean if values in the object are unique. Returns ------- @@ -1256,7 +1256,7 @@ def is_unique(self): def is_monotonic(self): """ Return boolean if values in the object are - monotonic_increasing + monotonic_increasing. .. versionadded:: 0.19.0 @@ -1273,7 +1273,7 @@ def is_monotonic(self): def is_monotonic_decreasing(self): """ Return boolean if values in the object are - monotonic_decreasing + monotonic_decreasing. .. versionadded:: 0.19.0 diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 0db76cd934d19..24407850d44a8 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -463,7 +463,7 @@ def categories(self): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self._ordered diff --git a/pandas/core/generic.py b/pandas/core/generic.py index ba50b971b6ff9..1d7e4eadea7e1 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -671,7 +671,7 @@ def transpose(self, *args, **kwargs): def swapaxes(self, axis1, axis2, copy=True): """ - Interchange axes and swap values axes appropriately + Interchange axes and swap values axes appropriately. Returns ------- @@ -1907,7 +1907,7 @@ def __array_wrap__(self, result, context=None): def to_dense(self): """ - Return dense representation of NDFrame (as opposed to sparse) + Return dense representation of NDFrame (as opposed to sparse). """ # compat return self @@ -3597,7 +3597,7 @@ class animal locomotion def select(self, crit, axis=0): """ - Return data corresponding to axis labels matching criteria + Return data corresponding to axis labels matching criteria. .. deprecated:: 0.21.0 Use df.loc[df.index.map(crit)] to select via labels @@ -4841,7 +4841,7 @@ def sample(self, n=None, frac=None, replace=False, weights=None, return self.take(locs, axis=axis, is_copy=False) _shared_docs['pipe'] = (r""" - Apply func(self, \*args, \*\*kwargs) + Apply func(self, \*args, \*\*kwargs). Parameters ---------- @@ -5533,7 +5533,7 @@ def as_blocks(self, copy=True): @property def blocks(self): """ - Internal property, property synonym for as_blocks() + Internal property, property synonym for as_blocks(). .. deprecated:: 0.21.0 """ @@ -5918,7 +5918,7 @@ def infer_objects(self): def fillna(self, value=None, method=None, axis=None, inplace=False, limit=None, downcast=None): """ - Fill NA/NaN values using the specified method + Fill NA/NaN values using the specified method. Parameters ---------- @@ -6103,14 +6103,14 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') ` + Synonym for :meth:`DataFrame.fillna(method='ffill') `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') ` + Synonym for :meth:`DataFrame.fillna(method='bfill') `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) @@ -8254,7 +8254,7 @@ def rank(self, axis=0, method='average', numeric_only=None, na_option='keep', ascending=True, pct=False): """ Compute numerical data ranks (1 through n) along axis. Equal values are - assigned a rank that is the average of the ranks of those values + assigned a rank that is the average of the ranks of those values. Parameters ---------- @@ -8316,7 +8316,7 @@ def ranker(data): _shared_docs['align'] = (""" Align two objects on their axes with the - specified join method for each axis Index + specified join method for each axis Index. Parameters ---------- @@ -9905,7 +9905,7 @@ def _add_numeric_operations(cls): @Substitution(outname='mad', desc="Return the mean absolute deviation of the values " - "for the requested axis", + "for the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9947,7 +9947,7 @@ def mad(self, axis=None, skipna=None, level=None): @Substitution(outname='compounded', desc="Return the compound percentage of the values for " - "the requested axis", name1=name, name2=name2, + "the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9977,31 +9977,31 @@ def compound(self, axis=None, skipna=None, level=None): cls.sum = _make_min_count_stat_function( cls, 'sum', name, name2, axis_descr, - 'Return the sum of the values for the requested axis', + 'Return the sum of the values for the requested axis.', nanops.nansum, _sum_examples) cls.mean = _make_stat_function( cls, 'mean', name, name2, axis_descr, - 'Return the mean of the values for the requested axis', + 'Return the mean of the values for the requested axis.', nanops.nanmean) cls.skew = _make_stat_function( cls, 'skew', name, name2, axis_descr, - 'Return unbiased skew over requested axis\nNormalized by N-1', + 'Return unbiased skew over requested axis\nNormalized by N-1.', nanops.nanskew) cls.kurt = _make_stat_function( cls, 'kurt', name, name2, axis_descr, "Return unbiased kurtosis over requested axis using Fisher's " "definition of\nkurtosis (kurtosis of normal == 0.0). Normalized " - "by N-1", + "by N-1.", nanops.nankurt) cls.kurtosis = cls.kurt cls.prod = _make_min_count_stat_function( cls, 'prod', name, name2, axis_descr, - 'Return the product of the values for the requested axis', + 'Return the product of the values for the requested axis.', nanops.nanprod, _prod_examples) cls.product = cls.prod cls.median = _make_stat_function( cls, 'median', name, name2, axis_descr, - 'Return the median of the values for the requested axis', + 'Return the median of the values for the requested axis.', nanops.nanmedian) cls.max = _make_stat_function( cls, 'max', name, name2, axis_descr, diff --git a/pandas/core/indexes/accessors.py b/pandas/core/indexes/accessors.py index 82b6b22be4a79..ecc96ca1ecc94 100644 --- a/pandas/core/indexes/accessors.py +++ b/pandas/core/indexes/accessors.py @@ -130,7 +130,7 @@ class DatetimeProperties(Properties): def to_pydatetime(self): """ - Return the data as an array of native Python datetime objects + Return the data as an array of native Python datetime objects. Timezone information is retained if present. diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index ec6743e205848..52d40f84cb1d9 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -2417,7 +2417,7 @@ def hist_series(self, by=None, ax=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, figsize=None, bins=10, **kwds): """ - Draw histogram of the input series using matplotlib + Draw histogram of the input series using matplotlib. Parameters ---------- @@ -2706,7 +2706,7 @@ def __call__(self, *args, **kwargs): class SeriesPlotMethods(BasePlotMethods): """ - Series plotting accessor and method + Series plotting accessor and method. Examples -------- @@ -2739,7 +2739,7 @@ def __call__(self, kind='line', ax=None, def line(self, **kwds): """ - Line plot + Line plot. Parameters ---------- @@ -2764,7 +2764,7 @@ def line(self, **kwds): def bar(self, **kwds): """ - Vertical bar plot + Vertical bar plot. Parameters ---------- @@ -2780,7 +2780,7 @@ def bar(self, **kwds): def barh(self, **kwds): """ - Horizontal bar plot + Horizontal bar plot. Parameters ---------- @@ -2796,7 +2796,7 @@ def barh(self, **kwds): def box(self, **kwds): """ - Boxplot + Boxplot. Parameters ---------- @@ -2812,7 +2812,7 @@ def box(self, **kwds): def hist(self, bins=10, **kwds): """ - Histogram + Histogram. Parameters ---------- @@ -2873,7 +2873,7 @@ def kde(self, bw_method=None, ind=None, **kwds): def area(self, **kwds): """ - Area plot + Area plot. Parameters ---------- @@ -2889,7 +2889,7 @@ def area(self, **kwds): def pie(self, **kwds): """ - Pie chart + Pie chart. Parameters ---------- diff --git a/scripts/tmp.xlsx b/scripts/tmp.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..030a0f83d63206d20e884777e6a90cc587791dbd GIT binary patch literal 5418 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 literal 0 HcmV?d00001 From 41e4757eb4f3f98e656ab87523af694630d55996 Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 19:57:49 -0500 Subject: [PATCH 10/18] fixed generic.py PEP8 - line too long issues --- pandas/core/generic.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 1d7e4eadea7e1..94fb48f0aae8d 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6103,14 +6103,16 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') `. + Synonym for :meth:`DataFrame.fillna(method='ffill') + `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') `. + Synonym for :meth:`DataFrame.fillna(method='bfill') + `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) From 074b925c08d3a24b193ac1d4cccff215c3be0669 Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 19:59:21 -0500 Subject: [PATCH 11/18] fixed generic.py PEP8 - trailing whitespace issues --- pandas/core/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 94fb48f0aae8d..11d1333851794 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6103,7 +6103,7 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') + Synonym for :meth:`DataFrame.fillna(method='ffill') `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, @@ -6111,7 +6111,7 @@ def ffill(self, axis=None, inplace=False, limit=None, downcast=None): def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') + Synonym for :meth:`DataFrame.fillna(method='bfill') `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, From a1e0df232f95f712104634cb76a1952109ee0067 Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 21:35:25 -0500 Subject: [PATCH 12/18] fixed minor errors --- pandas/core/accessor.py | 2 +- pandas/core/arrays/categorical.py | 4 ++-- pandas/core/arrays/datetimes.py | 18 +++++++++--------- scripts/tmp.xlsx | Bin 5418 -> 0 bytes 4 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 scripts/tmp.xlsx diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index 1beb097f58bdf..93b4ce31a1e25 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -59,7 +59,7 @@ def _delegate_method(self, name, *args, **kwargs): def _add_delegate_accessors(cls, delegate, accessors, typ, overwrite=False): """ - add accessors to cls from the delegate class. + Add accessors to cls from the delegate class. Parameters ---------- diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index c85c347b523d0..101d03cd55d40 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -782,7 +782,7 @@ def set_ordered(self, value, inplace=False): def as_ordered(self, inplace=False): """ - Sets the Categorical to be ordered. + Set the Categorical to be ordered. Parameters ---------- @@ -795,7 +795,7 @@ def as_ordered(self, inplace=False): def as_unordered(self, inplace=False): """ - Sets the Categorical to be unordered. + Set the Categorical to be unordered. Parameters ---------- diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 70b95d64608db..721d90723c0c7 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1070,19 +1070,19 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', "\n The year of the datetime.\n") + year = _field_accessor('year', 'Y', " The year of the datetime.") month = _field_accessor('month', 'M', - "\n The month as January=1, December=12. \n") - day = _field_accessor('day', 'D', "\nThe days of the datetime.\n") - hour = _field_accessor('hour', 'h', "\nThe hours of the datetime.\n") - minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime.\n") - second = _field_accessor('second', 's', "\nThe seconds of the datetime.\n") + " The month as January=1, December=12. ") + day = _field_accessor('day', 'D', "The days of the datetime.") + hour = _field_accessor('hour', 'h', "The hours of the datetime.") + minute = _field_accessor('minute', 'm', "The minutes of the datetime.") + second = _field_accessor('second', 's', "The seconds of the datetime.") microsecond = _field_accessor('microsecond', 'us', - "\nThe microseconds of the datetime.\n") + "The microseconds of the datetime.") nanosecond = _field_accessor('nanosecond', 'ns', - "\nThe nanoseconds of the datetime.\n") + "The nanoseconds of the datetime.") weekofyear = _field_accessor('weekofyear', 'woy', - "\nThe week ordinal of the year.\n") + "The week ordinal of the year.") week = weekofyear _dayofweek_doc = """ The day of the week with Monday=0, Sunday=6. diff --git a/scripts/tmp.xlsx b/scripts/tmp.xlsx deleted file mode 100644 index 030a0f83d63206d20e884777e6a90cc587791dbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5418 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 From 860bb8d931b78db27b4c690f28d00374cb9cb65b Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Sun, 9 Dec 2018 21:37:39 -0500 Subject: [PATCH 13/18] removed a few more \n --- pandas/core/arrays/datetimes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 721d90723c0c7..64d2ab0f43847 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -82,7 +82,7 @@ def f(self): return result f.__name__ = name - f.__doc__ = "\n{}\n".format(docstring) + f.__doc__ = "{}".format(docstring) return property(f) @@ -1124,7 +1124,7 @@ def date(self): weekday_name = _field_accessor( 'weekday_name', 'weekday_name', - "The name of day in a week (ex: Friday)\n\n.. deprecated:: 0.23.0") + "The name of day in a week (ex: Friday).. deprecated:: 0.23.0") dayofyear = _field_accessor('dayofyear', 'doy', "The ordinal day of the year.") From ce03033227ec250211efad0dde968a4c72b1f24c Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Tue, 11 Dec 2018 02:10:36 -0500 Subject: [PATCH 14/18] revert back \n --- pandas/core/arrays/datetimes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 64d2ab0f43847..721d90723c0c7 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -82,7 +82,7 @@ def f(self): return result f.__name__ = name - f.__doc__ = "{}".format(docstring) + f.__doc__ = "\n{}\n".format(docstring) return property(f) @@ -1124,7 +1124,7 @@ def date(self): weekday_name = _field_accessor( 'weekday_name', 'weekday_name', - "The name of day in a week (ex: Friday).. deprecated:: 0.23.0") + "The name of day in a week (ex: Friday)\n\n.. deprecated:: 0.23.0") dayofyear = _field_accessor('dayofyear', 'doy', "The ordinal day of the year.") From c10e7c5b2d3f1e24a009c1d4009fc58df798eafd Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Tue, 11 Dec 2018 08:43:07 -0500 Subject: [PATCH 15/18] revert \n --- pandas/core/arrays/datetimes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 6d504a331bdf0..4849ee1e3e665 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -82,7 +82,7 @@ def f(self): return result f.__name__ = name - f.__doc__ = "{}".format(docstring) + f.__doc__ = "\n{}\n".format(docstring) return property(f) From 5f67556a1dc8952ee6dd79a599e7bae8f874cc3a Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Tue, 11 Dec 2018 09:32:20 -0500 Subject: [PATCH 16/18] all my changes in a single commit --- pandas/core/accessor.py | 2 +- pandas/core/arrays/categorical.py | 6 ++--- pandas/core/arrays/datetimes.py | 18 +++++++-------- pandas/core/base.py | 6 ++--- pandas/core/dtypes/dtypes.py | 2 +- pandas/core/generic.py | 38 ++++++++++++++++--------------- pandas/core/indexes/accessors.py | 2 +- pandas/plotting/_core.py | 18 +++++++-------- 8 files changed, 47 insertions(+), 45 deletions(-) diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index fa1dc751c17da..93b4ce31a1e25 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -59,7 +59,7 @@ def _delegate_method(self, name, *args, **kwargs): def _add_delegate_accessors(cls, delegate, accessors, typ, overwrite=False): """ - add accessors to cls from the delegate class + Add accessors to cls from the delegate class. Parameters ---------- diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index abadd64b441b4..101d03cd55d40 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -477,7 +477,7 @@ def categories(self, categories): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self.dtype.ordered @@ -782,7 +782,7 @@ def set_ordered(self, value, inplace=False): def as_ordered(self, inplace=False): """ - Sets the Categorical to be ordered + Set the Categorical to be ordered. Parameters ---------- @@ -795,7 +795,7 @@ def as_ordered(self, inplace=False): def as_unordered(self, inplace=False): """ - Sets the Categorical to be unordered + Set the Categorical to be unordered. Parameters ---------- diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 72ab400b41c0c..4849ee1e3e665 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1070,19 +1070,19 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', "\n The year of the datetime\n") + year = _field_accessor('year', 'Y', "The year of the datetime.") month = _field_accessor('month', 'M', - "\n The month as January=1, December=12 \n") - day = _field_accessor('day', 'D', "\nThe days of the datetime\n") - hour = _field_accessor('hour', 'h', "\nThe hours of the datetime\n") - minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime\n") - second = _field_accessor('second', 's', "\nThe seconds of the datetime\n") + "The month as January=1, December=12. ") + day = _field_accessor('day', 'D', "The days of the datetime.") + hour = _field_accessor('hour', 'h', "The hours of the datetime.") + minute = _field_accessor('minute', 'm', "The minutes of the datetime.") + second = _field_accessor('second', 's', "The seconds of the datetime.") microsecond = _field_accessor('microsecond', 'us', - "\nThe microseconds of the datetime\n") + "The microseconds of the datetime.") nanosecond = _field_accessor('nanosecond', 'ns', - "\nThe nanoseconds of the datetime\n") + "The nanoseconds of the datetime.") weekofyear = _field_accessor('weekofyear', 'woy', - "\nThe week ordinal of the year\n") + "The week ordinal of the year.") week = weekofyear _dayofweek_doc = """ The day of the week with Monday=0, Sunday=6. diff --git a/pandas/core/base.py b/pandas/core/base.py index 1d2a0a2544dbc..161bf8fbf3482 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -1244,7 +1244,7 @@ def nunique(self, dropna=True): @property def is_unique(self): """ - Return boolean if values in the object are unique + Return boolean if values in the object are unique. Returns ------- @@ -1256,7 +1256,7 @@ def is_unique(self): def is_monotonic(self): """ Return boolean if values in the object are - monotonic_increasing + monotonic_increasing. .. versionadded:: 0.19.0 @@ -1273,7 +1273,7 @@ def is_monotonic(self): def is_monotonic_decreasing(self): """ Return boolean if values in the object are - monotonic_decreasing + monotonic_decreasing. .. versionadded:: 0.19.0 diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 0db76cd934d19..24407850d44a8 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -463,7 +463,7 @@ def categories(self): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self._ordered diff --git a/pandas/core/generic.py b/pandas/core/generic.py index ba50b971b6ff9..11d1333851794 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -671,7 +671,7 @@ def transpose(self, *args, **kwargs): def swapaxes(self, axis1, axis2, copy=True): """ - Interchange axes and swap values axes appropriately + Interchange axes and swap values axes appropriately. Returns ------- @@ -1907,7 +1907,7 @@ def __array_wrap__(self, result, context=None): def to_dense(self): """ - Return dense representation of NDFrame (as opposed to sparse) + Return dense representation of NDFrame (as opposed to sparse). """ # compat return self @@ -3597,7 +3597,7 @@ class animal locomotion def select(self, crit, axis=0): """ - Return data corresponding to axis labels matching criteria + Return data corresponding to axis labels matching criteria. .. deprecated:: 0.21.0 Use df.loc[df.index.map(crit)] to select via labels @@ -4841,7 +4841,7 @@ def sample(self, n=None, frac=None, replace=False, weights=None, return self.take(locs, axis=axis, is_copy=False) _shared_docs['pipe'] = (r""" - Apply func(self, \*args, \*\*kwargs) + Apply func(self, \*args, \*\*kwargs). Parameters ---------- @@ -5533,7 +5533,7 @@ def as_blocks(self, copy=True): @property def blocks(self): """ - Internal property, property synonym for as_blocks() + Internal property, property synonym for as_blocks(). .. deprecated:: 0.21.0 """ @@ -5918,7 +5918,7 @@ def infer_objects(self): def fillna(self, value=None, method=None, axis=None, inplace=False, limit=None, downcast=None): """ - Fill NA/NaN values using the specified method + Fill NA/NaN values using the specified method. Parameters ---------- @@ -6103,14 +6103,16 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') ` + Synonym for :meth:`DataFrame.fillna(method='ffill') + `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') ` + Synonym for :meth:`DataFrame.fillna(method='bfill') + `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) @@ -8254,7 +8256,7 @@ def rank(self, axis=0, method='average', numeric_only=None, na_option='keep', ascending=True, pct=False): """ Compute numerical data ranks (1 through n) along axis. Equal values are - assigned a rank that is the average of the ranks of those values + assigned a rank that is the average of the ranks of those values. Parameters ---------- @@ -8316,7 +8318,7 @@ def ranker(data): _shared_docs['align'] = (""" Align two objects on their axes with the - specified join method for each axis Index + specified join method for each axis Index. Parameters ---------- @@ -9905,7 +9907,7 @@ def _add_numeric_operations(cls): @Substitution(outname='mad', desc="Return the mean absolute deviation of the values " - "for the requested axis", + "for the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9947,7 +9949,7 @@ def mad(self, axis=None, skipna=None, level=None): @Substitution(outname='compounded', desc="Return the compound percentage of the values for " - "the requested axis", name1=name, name2=name2, + "the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9977,31 +9979,31 @@ def compound(self, axis=None, skipna=None, level=None): cls.sum = _make_min_count_stat_function( cls, 'sum', name, name2, axis_descr, - 'Return the sum of the values for the requested axis', + 'Return the sum of the values for the requested axis.', nanops.nansum, _sum_examples) cls.mean = _make_stat_function( cls, 'mean', name, name2, axis_descr, - 'Return the mean of the values for the requested axis', + 'Return the mean of the values for the requested axis.', nanops.nanmean) cls.skew = _make_stat_function( cls, 'skew', name, name2, axis_descr, - 'Return unbiased skew over requested axis\nNormalized by N-1', + 'Return unbiased skew over requested axis\nNormalized by N-1.', nanops.nanskew) cls.kurt = _make_stat_function( cls, 'kurt', name, name2, axis_descr, "Return unbiased kurtosis over requested axis using Fisher's " "definition of\nkurtosis (kurtosis of normal == 0.0). Normalized " - "by N-1", + "by N-1.", nanops.nankurt) cls.kurtosis = cls.kurt cls.prod = _make_min_count_stat_function( cls, 'prod', name, name2, axis_descr, - 'Return the product of the values for the requested axis', + 'Return the product of the values for the requested axis.', nanops.nanprod, _prod_examples) cls.product = cls.prod cls.median = _make_stat_function( cls, 'median', name, name2, axis_descr, - 'Return the median of the values for the requested axis', + 'Return the median of the values for the requested axis.', nanops.nanmedian) cls.max = _make_stat_function( cls, 'max', name, name2, axis_descr, diff --git a/pandas/core/indexes/accessors.py b/pandas/core/indexes/accessors.py index 82b6b22be4a79..ecc96ca1ecc94 100644 --- a/pandas/core/indexes/accessors.py +++ b/pandas/core/indexes/accessors.py @@ -130,7 +130,7 @@ class DatetimeProperties(Properties): def to_pydatetime(self): """ - Return the data as an array of native Python datetime objects + Return the data as an array of native Python datetime objects. Timezone information is retained if present. diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index ec6743e205848..52d40f84cb1d9 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -2417,7 +2417,7 @@ def hist_series(self, by=None, ax=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, figsize=None, bins=10, **kwds): """ - Draw histogram of the input series using matplotlib + Draw histogram of the input series using matplotlib. Parameters ---------- @@ -2706,7 +2706,7 @@ def __call__(self, *args, **kwargs): class SeriesPlotMethods(BasePlotMethods): """ - Series plotting accessor and method + Series plotting accessor and method. Examples -------- @@ -2739,7 +2739,7 @@ def __call__(self, kind='line', ax=None, def line(self, **kwds): """ - Line plot + Line plot. Parameters ---------- @@ -2764,7 +2764,7 @@ def line(self, **kwds): def bar(self, **kwds): """ - Vertical bar plot + Vertical bar plot. Parameters ---------- @@ -2780,7 +2780,7 @@ def bar(self, **kwds): def barh(self, **kwds): """ - Horizontal bar plot + Horizontal bar plot. Parameters ---------- @@ -2796,7 +2796,7 @@ def barh(self, **kwds): def box(self, **kwds): """ - Boxplot + Boxplot. Parameters ---------- @@ -2812,7 +2812,7 @@ def box(self, **kwds): def hist(self, bins=10, **kwds): """ - Histogram + Histogram. Parameters ---------- @@ -2873,7 +2873,7 @@ def kde(self, bw_method=None, ind=None, **kwds): def area(self, **kwds): """ - Area plot + Area plot. Parameters ---------- @@ -2889,7 +2889,7 @@ def area(self, **kwds): def pie(self, **kwds): """ - Pie chart + Pie chart. Parameters ---------- From 1950b089191e4a50e9116c76ea1c4654c1216a79 Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Tue, 11 Dec 2018 14:44:05 -0500 Subject: [PATCH 17/18] All my changes in a single commit --- pandas/core/accessor.py | 2 +- pandas/core/arrays/categorical.py | 6 ++--- pandas/core/arrays/datetimes.py | 18 +++++++-------- pandas/core/base.py | 6 ++--- pandas/core/dtypes/dtypes.py | 2 +- pandas/core/generic.py | 38 ++++++++++++++++--------------- pandas/core/indexes/accessors.py | 2 +- pandas/plotting/_core.py | 18 +++++++-------- 8 files changed, 47 insertions(+), 45 deletions(-) diff --git a/pandas/core/accessor.py b/pandas/core/accessor.py index fa1dc751c17da..93b4ce31a1e25 100644 --- a/pandas/core/accessor.py +++ b/pandas/core/accessor.py @@ -59,7 +59,7 @@ def _delegate_method(self, name, *args, **kwargs): def _add_delegate_accessors(cls, delegate, accessors, typ, overwrite=False): """ - add accessors to cls from the delegate class + Add accessors to cls from the delegate class. Parameters ---------- diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index abadd64b441b4..101d03cd55d40 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -477,7 +477,7 @@ def categories(self, categories): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self.dtype.ordered @@ -782,7 +782,7 @@ def set_ordered(self, value, inplace=False): def as_ordered(self, inplace=False): """ - Sets the Categorical to be ordered + Set the Categorical to be ordered. Parameters ---------- @@ -795,7 +795,7 @@ def as_ordered(self, inplace=False): def as_unordered(self, inplace=False): """ - Sets the Categorical to be unordered + Set the Categorical to be unordered. Parameters ---------- diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 72ab400b41c0c..4849ee1e3e665 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1070,19 +1070,19 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', "\n The year of the datetime\n") + year = _field_accessor('year', 'Y', "The year of the datetime.") month = _field_accessor('month', 'M', - "\n The month as January=1, December=12 \n") - day = _field_accessor('day', 'D', "\nThe days of the datetime\n") - hour = _field_accessor('hour', 'h', "\nThe hours of the datetime\n") - minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime\n") - second = _field_accessor('second', 's', "\nThe seconds of the datetime\n") + "The month as January=1, December=12. ") + day = _field_accessor('day', 'D', "The days of the datetime.") + hour = _field_accessor('hour', 'h', "The hours of the datetime.") + minute = _field_accessor('minute', 'm', "The minutes of the datetime.") + second = _field_accessor('second', 's', "The seconds of the datetime.") microsecond = _field_accessor('microsecond', 'us', - "\nThe microseconds of the datetime\n") + "The microseconds of the datetime.") nanosecond = _field_accessor('nanosecond', 'ns', - "\nThe nanoseconds of the datetime\n") + "The nanoseconds of the datetime.") weekofyear = _field_accessor('weekofyear', 'woy', - "\nThe week ordinal of the year\n") + "The week ordinal of the year.") week = weekofyear _dayofweek_doc = """ The day of the week with Monday=0, Sunday=6. diff --git a/pandas/core/base.py b/pandas/core/base.py index 1d2a0a2544dbc..161bf8fbf3482 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -1244,7 +1244,7 @@ def nunique(self, dropna=True): @property def is_unique(self): """ - Return boolean if values in the object are unique + Return boolean if values in the object are unique. Returns ------- @@ -1256,7 +1256,7 @@ def is_unique(self): def is_monotonic(self): """ Return boolean if values in the object are - monotonic_increasing + monotonic_increasing. .. versionadded:: 0.19.0 @@ -1273,7 +1273,7 @@ def is_monotonic(self): def is_monotonic_decreasing(self): """ Return boolean if values in the object are - monotonic_decreasing + monotonic_decreasing. .. versionadded:: 0.19.0 diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 0db76cd934d19..24407850d44a8 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -463,7 +463,7 @@ def categories(self): @property def ordered(self): """ - Whether the categories have an ordered relationship + Whether the categories have an ordered relationship. """ return self._ordered diff --git a/pandas/core/generic.py b/pandas/core/generic.py index ba50b971b6ff9..11d1333851794 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -671,7 +671,7 @@ def transpose(self, *args, **kwargs): def swapaxes(self, axis1, axis2, copy=True): """ - Interchange axes and swap values axes appropriately + Interchange axes and swap values axes appropriately. Returns ------- @@ -1907,7 +1907,7 @@ def __array_wrap__(self, result, context=None): def to_dense(self): """ - Return dense representation of NDFrame (as opposed to sparse) + Return dense representation of NDFrame (as opposed to sparse). """ # compat return self @@ -3597,7 +3597,7 @@ class animal locomotion def select(self, crit, axis=0): """ - Return data corresponding to axis labels matching criteria + Return data corresponding to axis labels matching criteria. .. deprecated:: 0.21.0 Use df.loc[df.index.map(crit)] to select via labels @@ -4841,7 +4841,7 @@ def sample(self, n=None, frac=None, replace=False, weights=None, return self.take(locs, axis=axis, is_copy=False) _shared_docs['pipe'] = (r""" - Apply func(self, \*args, \*\*kwargs) + Apply func(self, \*args, \*\*kwargs). Parameters ---------- @@ -5533,7 +5533,7 @@ def as_blocks(self, copy=True): @property def blocks(self): """ - Internal property, property synonym for as_blocks() + Internal property, property synonym for as_blocks(). .. deprecated:: 0.21.0 """ @@ -5918,7 +5918,7 @@ def infer_objects(self): def fillna(self, value=None, method=None, axis=None, inplace=False, limit=None, downcast=None): """ - Fill NA/NaN values using the specified method + Fill NA/NaN values using the specified method. Parameters ---------- @@ -6103,14 +6103,16 @@ def fillna(self, value=None, method=None, axis=None, inplace=False, def ffill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='ffill') ` + Synonym for :meth:`DataFrame.fillna(method='ffill') + `. """ return self.fillna(method='ffill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) def bfill(self, axis=None, inplace=False, limit=None, downcast=None): """ - Synonym for :meth:`DataFrame.fillna(method='bfill') ` + Synonym for :meth:`DataFrame.fillna(method='bfill') + `. """ return self.fillna(method='bfill', axis=axis, inplace=inplace, limit=limit, downcast=downcast) @@ -8254,7 +8256,7 @@ def rank(self, axis=0, method='average', numeric_only=None, na_option='keep', ascending=True, pct=False): """ Compute numerical data ranks (1 through n) along axis. Equal values are - assigned a rank that is the average of the ranks of those values + assigned a rank that is the average of the ranks of those values. Parameters ---------- @@ -8316,7 +8318,7 @@ def ranker(data): _shared_docs['align'] = (""" Align two objects on their axes with the - specified join method for each axis Index + specified join method for each axis Index. Parameters ---------- @@ -9905,7 +9907,7 @@ def _add_numeric_operations(cls): @Substitution(outname='mad', desc="Return the mean absolute deviation of the values " - "for the requested axis", + "for the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9947,7 +9949,7 @@ def mad(self, axis=None, skipna=None, level=None): @Substitution(outname='compounded', desc="Return the compound percentage of the values for " - "the requested axis", name1=name, name2=name2, + "the requested axis.", name1=name, name2=name2, axis_descr=axis_descr, min_count='', examples='') @Appender(_num_doc) @@ -9977,31 +9979,31 @@ def compound(self, axis=None, skipna=None, level=None): cls.sum = _make_min_count_stat_function( cls, 'sum', name, name2, axis_descr, - 'Return the sum of the values for the requested axis', + 'Return the sum of the values for the requested axis.', nanops.nansum, _sum_examples) cls.mean = _make_stat_function( cls, 'mean', name, name2, axis_descr, - 'Return the mean of the values for the requested axis', + 'Return the mean of the values for the requested axis.', nanops.nanmean) cls.skew = _make_stat_function( cls, 'skew', name, name2, axis_descr, - 'Return unbiased skew over requested axis\nNormalized by N-1', + 'Return unbiased skew over requested axis\nNormalized by N-1.', nanops.nanskew) cls.kurt = _make_stat_function( cls, 'kurt', name, name2, axis_descr, "Return unbiased kurtosis over requested axis using Fisher's " "definition of\nkurtosis (kurtosis of normal == 0.0). Normalized " - "by N-1", + "by N-1.", nanops.nankurt) cls.kurtosis = cls.kurt cls.prod = _make_min_count_stat_function( cls, 'prod', name, name2, axis_descr, - 'Return the product of the values for the requested axis', + 'Return the product of the values for the requested axis.', nanops.nanprod, _prod_examples) cls.product = cls.prod cls.median = _make_stat_function( cls, 'median', name, name2, axis_descr, - 'Return the median of the values for the requested axis', + 'Return the median of the values for the requested axis.', nanops.nanmedian) cls.max = _make_stat_function( cls, 'max', name, name2, axis_descr, diff --git a/pandas/core/indexes/accessors.py b/pandas/core/indexes/accessors.py index 82b6b22be4a79..ecc96ca1ecc94 100644 --- a/pandas/core/indexes/accessors.py +++ b/pandas/core/indexes/accessors.py @@ -130,7 +130,7 @@ class DatetimeProperties(Properties): def to_pydatetime(self): """ - Return the data as an array of native Python datetime objects + Return the data as an array of native Python datetime objects. Timezone information is retained if present. diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py index ec6743e205848..52d40f84cb1d9 100644 --- a/pandas/plotting/_core.py +++ b/pandas/plotting/_core.py @@ -2417,7 +2417,7 @@ def hist_series(self, by=None, ax=None, grid=True, xlabelsize=None, xrot=None, ylabelsize=None, yrot=None, figsize=None, bins=10, **kwds): """ - Draw histogram of the input series using matplotlib + Draw histogram of the input series using matplotlib. Parameters ---------- @@ -2706,7 +2706,7 @@ def __call__(self, *args, **kwargs): class SeriesPlotMethods(BasePlotMethods): """ - Series plotting accessor and method + Series plotting accessor and method. Examples -------- @@ -2739,7 +2739,7 @@ def __call__(self, kind='line', ax=None, def line(self, **kwds): """ - Line plot + Line plot. Parameters ---------- @@ -2764,7 +2764,7 @@ def line(self, **kwds): def bar(self, **kwds): """ - Vertical bar plot + Vertical bar plot. Parameters ---------- @@ -2780,7 +2780,7 @@ def bar(self, **kwds): def barh(self, **kwds): """ - Horizontal bar plot + Horizontal bar plot. Parameters ---------- @@ -2796,7 +2796,7 @@ def barh(self, **kwds): def box(self, **kwds): """ - Boxplot + Boxplot. Parameters ---------- @@ -2812,7 +2812,7 @@ def box(self, **kwds): def hist(self, bins=10, **kwds): """ - Histogram + Histogram. Parameters ---------- @@ -2873,7 +2873,7 @@ def kde(self, bw_method=None, ind=None, **kwds): def area(self, **kwds): """ - Area plot + Area plot. Parameters ---------- @@ -2889,7 +2889,7 @@ def area(self, **kwds): def pie(self, **kwds): """ - Pie chart + Pie chart. Parameters ---------- From 18350bf3c69612e875500049840a4a1fe0b2612d Mon Sep 17 00:00:00 2001 From: Yuecheng Wu Date: Tue, 11 Dec 2018 14:54:05 -0500 Subject: [PATCH 18/18] clean up branch history --- azure-pipelines.yml | 16 +- ci/azure/linux.yml | 79 --- ci/azure/{macos.yml => posix.yml} | 30 +- ci/azure/windows-py27.yml | 58 -- ci/azure/windows.yml | 14 +- doc/source/10min.rst | 14 +- doc/source/advanced.rst | 3 +- doc/source/api.rst | 3 +- doc/source/categorical.rst | 2 +- doc/source/contributing_docstring.rst | 6 +- doc/source/developer.rst | 2 + doc/source/dsintro.rst | 61 +- doc/source/ecosystem.rst | 2 + doc/source/enhancingperf.rst | 2 +- doc/source/extending.rst | 10 +- doc/source/merging.rst | 52 +- doc/source/options.rst | 9 +- doc/source/overview.rst | 2 +- doc/source/r_interface.rst | 1 - doc/source/releases.rst | 2 + doc/source/reshaping.rst | 25 +- doc/source/tutorials.rst | 2 + doc/source/visualization.rst | 55 +- doc/source/whatsnew/v0.22.0.rst | 4 +- doc/source/whatsnew/v0.23.0.rst | 53 +- doc/source/whatsnew/v0.23.1.rst | 12 +- doc/source/whatsnew/v0.23.2.rst | 5 - doc/source/whatsnew/v0.23.4.rst | 5 - doc/source/whatsnew/v0.24.0.rst | 105 ++-- pandas/_libs/tslibs/timestamps.pyx | 45 +- pandas/core/arrays/base.py | 2 + pandas/core/arrays/categorical.py | 12 +- pandas/core/arrays/datetimes.py | 13 +- pandas/core/arrays/sparse.py | 2 + pandas/core/computation/ops.py | 2 +- pandas/core/generic.py | 100 ++-- pandas/core/indexes/base.py | 3 +- pandas/core/indexes/category.py | 5 +- pandas/core/internals/blocks.py | 82 ++- .../tests/arrays/categorical/test_indexing.py | 121 ++++ pandas/tests/arrays/interval/test_interval.py | 14 +- pandas/tests/arrays/sparse/test_array.py | 4 +- pandas/tests/arrays/test_period.py | 15 + pandas/tests/extension/base/methods.py | 35 +- pandas/tests/extension/conftest.py | 6 +- pandas/tests/extension/json/test_json.py | 11 + pandas/tests/extension/test_categorical.py | 15 +- pandas/tests/extension/test_sparse.py | 31 + pandas/tests/frame/test_analytics.py | 15 +- .../indexes/datetimes/test_date_range.py | 11 + .../tests/indexing/multiindex/test_getitem.py | 562 +++++++++--------- pandas/tests/series/test_analytics.py | 20 +- scripts/validate_docstrings.py | 1 + setup.cfg | 25 +- tmp.xlsx | Bin 5417 -> 0 bytes 55 files changed, 1029 insertions(+), 757 deletions(-) delete mode 100644 ci/azure/linux.yml rename ci/azure/{macos.yml => posix.yml} (69%) delete mode 100644 ci/azure/windows-py27.yml delete mode 100644 tmp.xlsx diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 409b1ac8c9df3..1e4e43ac03815 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,28 +1,20 @@ # Adapted from https://github.com/numba/numba/blob/master/azure-pipelines.yml jobs: -# Mac and Linux could potentially use the same template -# except it isn't clear how to use a different build matrix -# for each, so for now they are separate -- template: ci/azure/macos.yml +# Mac and Linux use the same template +- template: ci/azure/posix.yml parameters: name: macOS vmImage: xcode9-macos10.13 -- template: ci/azure/linux.yml +- template: ci/azure/posix.yml parameters: name: Linux vmImage: ubuntu-16.04 -# Windows Python 2.7 needs VC 9.0 installed, and not sure -# how to make that a conditional task, so for now these are -# separate templates as well +# Windows Python 2.7 needs VC 9.0 installed, handled in the template - template: ci/azure/windows.yml parameters: name: Windows vmImage: vs2017-win2016 -- template: ci/azure/windows-py27.yml - parameters: - name: WindowsPy27 - vmImage: vs2017-win2016 - job: 'Checks_and_doc' pool: diff --git a/ci/azure/linux.yml b/ci/azure/linux.yml deleted file mode 100644 index fe64307e9d08f..0000000000000 --- a/ci/azure/linux.yml +++ /dev/null @@ -1,79 +0,0 @@ -parameters: - name: '' - vmImage: '' - -jobs: -- job: ${{ parameters.name }} - pool: - vmImage: ${{ parameters.vmImage }} - strategy: - maxParallel: 11 - matrix: - py27_np_120: - ENV_FILE: ci/deps/azure-27-compat.yaml - CONDA_PY: "27" - PATTERN: "not slow and not network" - - py37_locale: - ENV_FILE: ci/deps/azure-37-locale.yaml - CONDA_PY: "37" - PATTERN: "not slow and not network" - LOCALE_OVERRIDE: "zh_CN.UTF-8" - - py36_locale_slow: - ENV_FILE: ci/deps/azure-36-locale_slow.yaml - CONDA_PY: "36" - PATTERN: "not slow and not network" - LOCALE_OVERRIDE: "it_IT.UTF-8" - - steps: - - script: | - if [ "$(uname)" == "Linux" ]; then sudo apt-get install -y libc6-dev-i386; fi - echo "Installing Miniconda"{ - ci/incremental/install_miniconda.sh - export PATH=$HOME/miniconda3/bin:$PATH - echo "Setting up Conda environment" - ci/incremental/setup_conda_environment.sh - displayName: 'Before Install' - - script: | - export PATH=$HOME/miniconda3/bin:$PATH - source activate pandas-dev - ci/incremental/build.sh - displayName: 'Build' - - script: | - export PATH=$HOME/miniconda3/bin:$PATH - source activate pandas-dev - ci/run_tests.sh - displayName: 'Test' - - script: | - export PATH=$HOME/miniconda3/bin:$PATH - source activate pandas-dev && pushd /tmp && python -c "import pandas; pandas.show_versions();" && popd - - task: PublishTestResults@2 - inputs: - testResultsFiles: 'test-data-*.xml' - testRunTitle: 'Linux' - - powershell: | - $junitXml = "test-data-single.xml" - $(Get-Content $junitXml | Out-String) -match 'failures="(.*?)"' - if ($matches[1] -eq 0) - { - Write-Host "No test failures in test-data-single" - } - else - { - # note that this will produce $LASTEXITCODE=1 - Write-Error "$($matches[1]) tests failed" - } - - $junitXmlMulti = "test-data-multiple.xml" - $(Get-Content $junitXmlMulti | Out-String) -match 'failures="(.*?)"' - if ($matches[1] -eq 0) - { - Write-Host "No test failures in test-data-multi" - } - else - { - # note that this will produce $LASTEXITCODE=1 - Write-Error "$($matches[1]) tests failed" - } - displayName: Check for test failures diff --git a/ci/azure/macos.yml b/ci/azure/posix.yml similarity index 69% rename from ci/azure/macos.yml rename to ci/azure/posix.yml index 98409576a5a87..374a82a5ed7d0 100644 --- a/ci/azure/macos.yml +++ b/ci/azure/posix.yml @@ -7,12 +7,30 @@ jobs: pool: vmImage: ${{ parameters.vmImage }} strategy: - maxParallel: 11 matrix: - py35_np_120: - ENV_FILE: ci/deps/azure-macos-35.yaml - CONDA_PY: "35" - PATTERN: "not slow and not network" + ${{ if eq(parameters.name, 'macOS') }}: + py35_np_120: + ENV_FILE: ci/deps/azure-macos-35.yaml + CONDA_PY: "35" + PATTERN: "not slow and not network" + + ${{ if eq(parameters.name, 'Linux') }}: + py27_np_120: + ENV_FILE: ci/deps/azure-27-compat.yaml + CONDA_PY: "27" + PATTERN: "not slow and not network" + + py37_locale: + ENV_FILE: ci/deps/azure-37-locale.yaml + CONDA_PY: "37" + PATTERN: "not slow and not network" + LOCALE_OVERRIDE: "zh_CN.UTF-8" + + py36_locale_slow: + ENV_FILE: ci/deps/azure-36-locale_slow.yaml + CONDA_PY: "36" + PATTERN: "not slow and not network" + LOCALE_OVERRIDE: "it_IT.UTF-8" steps: - script: | @@ -39,7 +57,7 @@ jobs: - task: PublishTestResults@2 inputs: testResultsFiles: 'test-data-*.xml' - testRunTitle: 'MacOS-35' + testRunTitle: ${{ format('{0}-$(CONDA_PY)', parameters.name) }} - powershell: | $junitXml = "test-data-single.xml" $(Get-Content $junitXml | Out-String) -match 'failures="(.*?)"' diff --git a/ci/azure/windows-py27.yml b/ci/azure/windows-py27.yml deleted file mode 100644 index 0d9aea816c4ad..0000000000000 --- a/ci/azure/windows-py27.yml +++ /dev/null @@ -1,58 +0,0 @@ -parameters: - name: '' - vmImage: '' - -jobs: -- job: ${{ parameters.name }} - pool: - vmImage: ${{ parameters.vmImage }} - strategy: - maxParallel: 11 - matrix: - py36_np121: - ENV_FILE: ci/deps/azure-windows-27.yaml - CONDA_PY: "27" - - steps: - - task: CondaEnvironment@1 - inputs: - updateConda: no - packageSpecs: '' - - # Need to install VC 9.0 only for Python 2.7 - # Once we understand how to do tasks conditional on build matrix variables - # we could merge this into azure-windows.yml - - powershell: | - $wc = New-Object net.webclient - $wc.Downloadfile("https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi", "VCForPython27.msi") - Start-Process "VCForPython27.msi" /qn -Wait - displayName: 'Install VC 9.0' - - - script: | - ci\\incremental\\setup_conda_environment.cmd - displayName: 'Before Install' - - script: | - call activate pandas-dev - ci\\incremental\\build.cmd - displayName: 'Build' - - script: | - call activate pandas-dev - pytest -m "not slow and not network" --junitxml=test-data.xml pandas -n 2 -r sxX --strict --durations=10 %* - displayName: 'Test' - - task: PublishTestResults@2 - inputs: - testResultsFiles: 'test-data.xml' - testRunTitle: 'Windows 27' - - powershell: | - $junitXml = "test-data.xml" - $(Get-Content $junitXml | Out-String) -match 'failures="(.*?)"' - if ($matches[1] -eq 0) - { - Write-Host "No test failures in test-data" - } - else - { - # note that this will produce $LASTEXITCODE=1 - Write-Error "$($matches[1]) tests failed" - } - displayName: Check for test failures diff --git a/ci/azure/windows.yml b/ci/azure/windows.yml index b69c210ca27ba..cece002024936 100644 --- a/ci/azure/windows.yml +++ b/ci/azure/windows.yml @@ -7,18 +7,28 @@ jobs: pool: vmImage: ${{ parameters.vmImage }} strategy: - maxParallel: 11 matrix: py36_np14: ENV_FILE: ci/deps/azure-windows-36.yaml CONDA_PY: "36" + py27_np121: + ENV_FILE: ci/deps/azure-windows-27.yaml + CONDA_PY: "27" + steps: - task: CondaEnvironment@1 inputs: updateConda: no packageSpecs: '' + - powershell: | + $wc = New-Object net.webclient + $wc.Downloadfile("https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi", "VCForPython27.msi") + Start-Process "VCForPython27.msi" /qn -Wait + displayName: 'Install VC 9.0 only for Python 2.7' + condition: eq(variables.CONDA_PY, '27') + - script: | ci\\incremental\\setup_conda_environment.cmd displayName: 'Before Install' @@ -33,7 +43,7 @@ jobs: - task: PublishTestResults@2 inputs: testResultsFiles: 'test-data.xml' - testRunTitle: 'Windows 36' + testRunTitle: 'Windows-$(CONDA_PY)' - powershell: | $junitXml = "test-data.xml" $(Get-Content $junitXml | Out-String) -match 'failures="(.*?)"' diff --git a/doc/source/10min.rst b/doc/source/10min.rst index 53618e008a403..a7557e6e1d1c2 100644 --- a/doc/source/10min.rst +++ b/doc/source/10min.rst @@ -51,7 +51,7 @@ Creating a ``DataFrame`` by passing a dict of objects that can be converted to s 'F': 'foo'}) df2 -The columns of the resulting ``DataFrame`` have different +The columns of the resulting ``DataFrame`` have different :ref:`dtypes `. .. ipython:: python @@ -65,7 +65,7 @@ will be completed: .. ipython:: @verbatim - In [1]: df2. + In [1]: df2. # noqa: E225, E999 df2.A df2.bool df2.abs df2.boxplot df2.add df2.C @@ -495,7 +495,7 @@ Another example that can be given is: Append ~~~~~~ -Append rows to a dataframe. See the :ref:`Appending ` +Append rows to a dataframe. See the :ref:`Appending ` section. .. ipython:: python @@ -528,14 +528,14 @@ See the :ref:`Grouping section `. 'D': np.random.randn(8)}) df -Grouping and then applying the :meth:`~DataFrame.sum` function to the resulting +Grouping and then applying the :meth:`~DataFrame.sum` function to the resulting groups. .. ipython:: python df.groupby('A').sum() -Grouping by multiple columns forms a hierarchical index, and again we can +Grouping by multiple columns forms a hierarchical index, and again we can apply the ``sum`` function. .. ipython:: python @@ -671,7 +671,7 @@ Convert the raw grades to a categorical data type. df["grade"] = df["raw_grade"].astype("category") df["grade"] -Rename the categories to more meaningful names (assigning to +Rename the categories to more meaningful names (assigning to ``Series.cat.categories`` is inplace!). .. ipython:: python @@ -720,7 +720,7 @@ See the :ref:`Plotting ` docs. @savefig series_plot_basic.png ts.plot() -On a DataFrame, the :meth:`~DataFrame.plot` method is a convenience to plot all +On a DataFrame, the :meth:`~DataFrame.plot` method is a convenience to plot all of the columns with labels: .. ipython:: python diff --git a/doc/source/advanced.rst b/doc/source/advanced.rst index 822bc7407a0c7..483921393f3ea 100644 --- a/doc/source/advanced.rst +++ b/doc/source/advanced.rst @@ -563,7 +563,8 @@ they need to be sorted. As with any index, you can use :meth:`~DataFrame.sort_in .. ipython:: python - import random; random.shuffle(tuples) + import random + random.shuffle(tuples) s = pd.Series(np.random.randn(8), index=pd.MultiIndex.from_tuples(tuples)) s s.sort_index() diff --git a/doc/source/api.rst b/doc/source/api.rst index 49c89a53e7b17..bcef5567c23e5 100644 --- a/doc/source/api.rst +++ b/doc/source/api.rst @@ -1,6 +1,7 @@ -.. currentmodule:: pandas .. _api: +{{ header }} + ************* API Reference ************* diff --git a/doc/source/categorical.rst b/doc/source/categorical.rst index e57fd0ac0f96d..721e032b8bb92 100644 --- a/doc/source/categorical.rst +++ b/doc/source/categorical.rst @@ -782,7 +782,7 @@ Setting values by assigning categorical data will also check that the `categorie df try: df.loc["j":"k", "cats"] = pd.Categorical(["b", "b"], - categories=["a", "b", "c"]) + categories=["a", "b", "c"]) except ValueError as e: print("ValueError:", str(e)) diff --git a/doc/source/contributing_docstring.rst b/doc/source/contributing_docstring.rst index 2f8ffc2e07c71..7c7847a47a1a2 100644 --- a/doc/source/contributing_docstring.rst +++ b/doc/source/contributing_docstring.rst @@ -1,13 +1,11 @@ .. _docstring: +{{ header }} + ====================== pandas docstring guide ====================== -.. note:: - `Video tutorial: Pandas docstring guide - `_ by Frank Akogun. - About docstrings and standards ------------------------------ diff --git a/doc/source/developer.rst b/doc/source/developer.rst index ba6cec93d02e4..a283920ae4377 100644 --- a/doc/source/developer.rst +++ b/doc/source/developer.rst @@ -1,5 +1,7 @@ .. _developer: +{{ header }} + .. currentmodule:: pandas ********* diff --git a/doc/source/dsintro.rst b/doc/source/dsintro.rst index 8bdb0005de53c..d4a83b6807fd5 100644 --- a/doc/source/dsintro.rst +++ b/doc/source/dsintro.rst @@ -71,7 +71,7 @@ Series can be instantiated from dicts: .. ipython:: python - d = {'b' : 1, 'a' : 0, 'c' : 2} + d = {'b': 1, 'a': 0, 'c': 2} pd.Series(d) .. note:: @@ -92,7 +92,7 @@ index will be pulled out. .. ipython:: python - d = {'a' : 0., 'b' : 1., 'c' : 2.} + d = {'a': 0., 'b': 1., 'c': 2.} pd.Series(d) pd.Series(d, index=['b', 'c', 'd', 'a']) @@ -304,8 +304,8 @@ keys. .. ipython:: python - d = {'one' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']), - 'two' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])} + d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']), + 'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])} df = pd.DataFrame(d) df @@ -334,8 +334,8 @@ result will be ``range(n)``, where ``n`` is the array length. .. ipython:: python - d = {'one' : [1., 2., 3., 4.], - 'two' : [4., 3., 2., 1.]} + d = {'one': [1., 2., 3., 4.], + 'two': [4., 3., 2., 1.]} pd.DataFrame(d) pd.DataFrame(d, index=['a', 'b', 'c', 'd']) @@ -346,8 +346,8 @@ This case is handled identically to a dict of arrays. .. ipython:: python - data = np.zeros((2,), dtype=[('A', 'i4'),('B', 'f4'),('C', 'a10')]) - data[:] = [(1,2.,'Hello'), (2,3.,"World")] + data = np.zeros((2, ), dtype=[('A', 'i4'), ('B', 'f4'), ('C', 'a10')]) + data[:] = [(1, 2., 'Hello'), (2, 3., "World")] pd.DataFrame(data) pd.DataFrame(data, index=['first', 'second']) @@ -507,8 +507,7 @@ derived from existing columns. iris = pd.read_csv('data/iris.data') iris.head() - - (iris.assign(sepal_ratio = iris['SepalWidth'] / iris['SepalLength']) + (iris.assign(sepal_ratio=iris['SepalWidth'] / iris['SepalLength']) .head()) In the example above, we inserted a precomputed value. We can also pass in @@ -516,8 +515,7 @@ a function of one argument to be evaluated on the DataFrame being assigned to. .. ipython:: python - iris.assign(sepal_ratio = lambda x: (x['SepalWidth'] / - x['SepalLength'])).head() + iris.assign(sepal_ratio=lambda x: (x['SepalWidth'] / x['SepalLength'])).head() ``assign`` **always** returns a copy of the data, leaving the original DataFrame untouched. @@ -532,8 +530,8 @@ greater than 5, calculate the ratio, and plot: @savefig basics_assign.png (iris.query('SepalLength > 5') - .assign(SepalRatio = lambda x: x.SepalWidth / x.SepalLength, - PetalRatio = lambda x: x.PetalWidth / x.PetalLength) + .assign(SepalRatio=lambda x: x.SepalWidth / x.SepalLength, + PetalRatio=lambda x: x.PetalWidth / x.PetalLength) .plot(kind='scatter', x='SepalRatio', y='PetalRatio')) Since a function is passed in, the function is computed on the DataFrame @@ -705,8 +703,8 @@ Boolean operators work as well: .. ipython:: python - df1 = pd.DataFrame({'a' : [1, 0, 1], 'b' : [0, 1, 1] }, dtype=bool) - df2 = pd.DataFrame({'a' : [0, 1, 1], 'b' : [1, 1, 0] }, dtype=bool) + df1 = pd.DataFrame({'a': [1, 0, 1], 'b': [0, 1, 1]}, dtype=bool) + df2 = pd.DataFrame({'a': [0, 1, 1], 'b': [1, 1, 0]}, dtype=bool) df1 & df2 df1 | df2 df1 ^ df2 @@ -746,7 +744,7 @@ Similarly, the dot method on Series implements dot product: .. ipython:: python - s1 = pd.Series(np.arange(5,10)) + s1 = pd.Series(np.arange(5, 10)) s1.dot(s1) DataFrame is not intended to be a drop-in replacement for ndarray as its @@ -777,7 +775,7 @@ R package): :okwarning: # restore GlobalPrintConfig - pd.reset_option('^display\.') + pd.reset_option(r'^display\.') However, using ``to_string`` will return a string representation of the DataFrame in tabular form, though it won't always fit the console width: @@ -798,7 +796,7 @@ option: .. ipython:: python - pd.set_option('display.width', 40) # default is 80 + pd.set_option('display.width', 40) # default is 80 pd.DataFrame(np.random.randn(3, 12)) @@ -806,14 +804,14 @@ You can adjust the max width of the individual columns by setting ``display.max_ .. ipython:: python - datafile={'filename': ['filename_01','filename_02'], - 'path': ["media/user_name/storage/folder_01/filename_01", - "media/user_name/storage/folder_02/filename_02"]} + datafile = {'filename': ['filename_01', 'filename_02'], + 'path': ["media/user_name/storage/folder_01/filename_01", + "media/user_name/storage/folder_02/filename_02"]} - pd.set_option('display.max_colwidth',30) + pd.set_option('display.max_colwidth', 30) pd.DataFrame(datafile) - pd.set_option('display.max_colwidth',100) + pd.set_option('display.max_colwidth', 100) pd.DataFrame(datafile) .. ipython:: python @@ -833,8 +831,8 @@ accessed like an attribute: .. ipython:: python - df = pd.DataFrame({'foo1' : np.random.randn(5), - 'foo2' : np.random.randn(5)}) + df = pd.DataFrame({'foo1': np.random.randn(5), + 'foo2': np.random.randn(5)}) df df.foo1 @@ -843,7 +841,7 @@ completion mechanism so they can be tab-completed: .. code-block:: ipython - In [5]: df.fo + In [5]: df.fo # noqa: E225, E999 df.foo1 df.foo2 .. _basics.panel: @@ -890,8 +888,8 @@ From dict of DataFrame objects .. ipython:: python :okwarning: - data = {'Item1' : pd.DataFrame(np.random.randn(4, 3)), - 'Item2' : pd.DataFrame(np.random.randn(4, 2))} + data = {'Item1': pd.DataFrame(np.random.randn(4, 3)), + 'Item2': pd.DataFrame(np.random.randn(4, 2))} pd.Panel(data) Note that the values in the dict need only be **convertible to @@ -947,8 +945,9 @@ From DataFrame using ``to_panel`` method .. ipython:: python :okwarning: - midx = pd.MultiIndex(levels=[['one', 'two'], ['x','y']], codes=[[1,1,0,0],[1,0,1,0]]) - df = pd.DataFrame({'A' : [1, 2, 3, 4], 'B': [5, 6, 7, 8]}, index=midx) + midx = pd.MultiIndex(levels=[['one', 'two'], ['x', 'y']], + codes=[[1, 1, 0, 0], [1, 0, 1, 0]]) + df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]}, index=midx) df.to_panel() .. _dsintro.panel_item_selection: diff --git a/doc/source/ecosystem.rst b/doc/source/ecosystem.rst index ad389bbe35b71..e0c47e2f2ba7e 100644 --- a/doc/source/ecosystem.rst +++ b/doc/source/ecosystem.rst @@ -1,5 +1,7 @@ .. _ecosystem: +{{ header }} + **************** pandas Ecosystem **************** diff --git a/doc/source/enhancingperf.rst b/doc/source/enhancingperf.rst index c0546d653d532..429ff91d88e41 100644 --- a/doc/source/enhancingperf.rst +++ b/doc/source/enhancingperf.rst @@ -469,7 +469,7 @@ These operations are supported by :func:`pandas.eval`: * Simple variable evaluation, e.g., ``pd.eval('df')`` (this is not very useful) * Math functions: `sin`, `cos`, `exp`, `log`, `expm1`, `log1p`, `sqrt`, `sinh`, `cosh`, `tanh`, `arcsin`, `arccos`, `arctan`, `arccosh`, - `arcsinh`, `arctanh`, `abs` and `arctan2`. + `arcsinh`, `arctanh`, `abs`, `arctan2` and `log10`. This Python syntax is **not** allowed: diff --git a/doc/source/extending.rst b/doc/source/extending.rst index 7046981a3a364..35d0dab7c3a77 100644 --- a/doc/source/extending.rst +++ b/doc/source/extending.rst @@ -1,5 +1,7 @@ .. _extending: +{{ header }} + **************** Extending Pandas **************** @@ -160,6 +162,8 @@ your ``MyExtensionArray`` class, as follows: .. code-block:: python + from pandas.core.arrays import ExtensionArray, ExtensionScalarOpsMixin + class MyExtensionArray(ExtensionArray, ExtensionScalarOpsMixin): pass @@ -269,7 +273,7 @@ Below example shows how to define ``SubclassedSeries`` and ``SubclassedDataFrame .. code-block:: python - class SubclassedSeries(Series): + class SubclassedSeries(pd.Series): @property def _constructor(self): @@ -280,7 +284,7 @@ Below example shows how to define ``SubclassedSeries`` and ``SubclassedDataFrame return SubclassedDataFrame - class SubclassedDataFrame(DataFrame): + class SubclassedDataFrame(pd.DataFrame): @property def _constructor(self): @@ -342,7 +346,7 @@ Below is an example to define two original properties, "internal_cache" as a tem .. code-block:: python - class SubclassedDataFrame2(DataFrame): + class SubclassedDataFrame2(pd.DataFrame): # temporary properties _internal_names = pd.DataFrame._internal_names + ['internal_cache'] diff --git a/doc/source/merging.rst b/doc/source/merging.rst index af767d7687749..6f7ee4917f494 100644 --- a/doc/source/merging.rst +++ b/doc/source/merging.rst @@ -5,6 +5,7 @@ .. ipython:: python :suppress: + from matplotlib import pyplot as plt import pandas.util._doctools as doctools p = doctools.TablePlotter() @@ -38,19 +39,19 @@ a simple example: 'B': ['B0', 'B1', 'B2', 'B3'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']}, - index=[0, 1, 2, 3]) + index=[0, 1, 2, 3]) df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'], 'B': ['B4', 'B5', 'B6', 'B7'], 'C': ['C4', 'C5', 'C6', 'C7'], 'D': ['D4', 'D5', 'D6', 'D7']}, - index=[4, 5, 6, 7]) + index=[4, 5, 6, 7]) df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'], 'B': ['B8', 'B9', 'B10', 'B11'], 'C': ['C8', 'C9', 'C10', 'C11'], 'D': ['D8', 'D9', 'D10', 'D11']}, - index=[8, 9, 10, 11]) + index=[8, 9, 10, 11]) frames = [df1, df2, df3] result = pd.concat(frames) @@ -379,7 +380,7 @@ Through the ``keys`` argument we can override the existing column names. .. ipython:: python - pd.concat([s3, s4, s5], axis=1, keys=['red','blue','yellow']) + pd.concat([s3, s4, s5], axis=1, keys=['red', 'blue', 'yellow']) Let's consider a variation of the very first example presented: @@ -436,8 +437,8 @@ do so using the ``levels`` argument: .. ipython:: python result = pd.concat(pieces, keys=['x', 'y', 'z'], - levels=[['z', 'y', 'x', 'w']], - names=['group_key']) + levels=[['z', 'y', 'x', 'w']], + names=['group_key']) .. ipython:: python :suppress: @@ -725,9 +726,9 @@ Here is another example with duplicate join keys in DataFrames: .. ipython:: python - left = pd.DataFrame({'A' : [1,2], 'B' : [2, 2]}) + left = pd.DataFrame({'A': [1, 2], 'B': [2, 2]}) - right = pd.DataFrame({'A' : [4,5,6], 'B': [2,2,2]}) + right = pd.DataFrame({'A': [4, 5, 6], 'B': [2, 2, 2]}) result = pd.merge(left, right, on='B', how='outer') @@ -800,8 +801,8 @@ that takes on values: .. ipython:: python - df1 = pd.DataFrame({'col1': [0, 1], 'col_left':['a', 'b']}) - df2 = pd.DataFrame({'col1': [1, 2, 2],'col_right':[2, 2, 2]}) + df1 = pd.DataFrame({'col1': [0, 1], 'col_left': ['a', 'b']}) + df2 = pd.DataFrame({'col1': [1, 2, 2], 'col_right': [2, 2, 2]}) pd.merge(df1, df2, on='col1', how='outer', indicator=True) The ``indicator`` argument will also accept string arguments, in which case the indicator function will use the value of the passed string as the name for the indicator column. @@ -856,7 +857,8 @@ The left frame. X = X.astype(CategoricalDtype(categories=['foo', 'bar'])) left = pd.DataFrame({'X': X, - 'Y': np.random.choice(['one', 'two', 'three'], size=(10,))}) + 'Y': np.random.choice(['one', 'two', 'three'], + size=(10,))}) left left.dtypes @@ -864,11 +866,9 @@ The right frame. .. ipython:: python - right = pd.DataFrame({ - 'X': pd.Series(['foo', 'bar'], - dtype=CategoricalDtype(['foo', 'bar'])), - 'Z': [1, 2] - }) + right = pd.DataFrame({'X': pd.Series(['foo', 'bar'], + dtype=CategoricalDtype(['foo', 'bar'])), + 'Z': [1, 2]}) right right.dtypes @@ -902,11 +902,11 @@ potentially differently-indexed ``DataFrames`` into a single result left = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2']}, - index=['K0', 'K1', 'K2']) + index=['K0', 'K1', 'K2']) right = pd.DataFrame({'C': ['C0', 'C2', 'C3'], 'D': ['D0', 'D2', 'D3']}, - index=['K0', 'K2', 'K3']) + index=['K0', 'K2', 'K3']) result = left.join(right) @@ -998,7 +998,7 @@ join key), using ``join`` may be more convenient. Here is a simple example: right = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']}, - index=['K0', 'K1']) + index=['K0', 'K1']) result = left.join(right, on='key') @@ -1037,8 +1037,8 @@ To join on multiple keys, the passed DataFrame must have a ``MultiIndex``: index = pd.MultiIndex.from_tuples([('K0', 'K0'), ('K1', 'K0'), ('K2', 'K0'), ('K2', 'K1')]) right = pd.DataFrame({'C': ['C0', 'C1', 'C2', 'C3'], - 'D': ['D0', 'D1', 'D2', 'D3']}, - index=index) + 'D': ['D0', 'D1', 'D2', 'D3']}, + index=index) Now this can be joined by passing the two key column names: @@ -1133,12 +1133,12 @@ the left argument, as in this example: leftindex = pd.MultiIndex.from_product([list('abc'), list('xy'), [1, 2]], names=['abc', 'xy', 'num']) - left = pd.DataFrame({'v1' : range(12)}, index=leftindex) + left = pd.DataFrame({'v1': range(12)}, index=leftindex) left rightindex = pd.MultiIndex.from_product([list('abc'), list('xy')], names=['abc', 'xy']) - right = pd.DataFrame({'v2': [100*i for i in range(1, 7)]}, index=rightindex) + right = pd.DataFrame({'v2': [100 * i for i in range(1, 7)]}, index=rightindex) right left.join(right, on=['abc', 'xy'], how='inner') @@ -1153,17 +1153,17 @@ done using the following code. names=['key', 'X']) left = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2']}, - index=leftindex) + index=leftindex) rightindex = pd.MultiIndex.from_tuples([('K0', 'Y0'), ('K1', 'Y1'), ('K2', 'Y2'), ('K2', 'Y3')], names=['key', 'Y']) right = pd.DataFrame({'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']}, - index=rightindex) + index=rightindex) result = pd.merge(left.reset_index(), right.reset_index(), - on=['key'], how='inner').set_index(['key','X','Y']) + on=['key'], how='inner').set_index(['key', 'X', 'Y']) .. ipython:: python :suppress: diff --git a/doc/source/options.rst b/doc/source/options.rst index dc4d0da32008c..31359c337fdb8 100644 --- a/doc/source/options.rst +++ b/doc/source/options.rst @@ -1,13 +1,6 @@ .. _options: -.. currentmodule:: pandas - -.. ipython:: python - :suppress: - - import pandas as pd - import numpy as np - np.random.seed(123456) +{{ header }} ******************** Options and Settings diff --git a/doc/source/overview.rst b/doc/source/overview.rst index b71f4bfa2f3be..351cc09c07cab 100644 --- a/doc/source/overview.rst +++ b/doc/source/overview.rst @@ -1,6 +1,6 @@ .. _overview: -.. currentmodule:: pandas +{{ header }} **************** Package overview diff --git a/doc/source/r_interface.rst b/doc/source/r_interface.rst index 4ec43a64cf98a..9839bba4884d4 100644 --- a/doc/source/r_interface.rst +++ b/doc/source/r_interface.rst @@ -2,7 +2,6 @@ {{ header }} - ****************** rpy2 / R interface ****************** diff --git a/doc/source/releases.rst b/doc/source/releases.rst index 0167903cce8bc..491569c69115b 100644 --- a/doc/source/releases.rst +++ b/doc/source/releases.rst @@ -1,5 +1,7 @@ .. _release: +{{ header }} + ************* Release Notes ************* diff --git a/doc/source/reshaping.rst b/doc/source/reshaping.rst index 059e6eb2138f3..d9fbb52f2e56a 100644 --- a/doc/source/reshaping.rst +++ b/doc/source/reshaping.rst @@ -18,12 +18,12 @@ Reshaping by pivoting DataFrame objects tm.N = 3 def unpivot(frame): - N, K = frame.shape - data = {'value': frame.to_numpy().ravel('F'), - 'variable': np.asarray(frame.columns).repeat(N), - 'date': np.tile(np.asarray(frame.index), K)} - columns = ['date', 'variable', 'value'] - return pd.DataFrame(data, columns=columns) + N, K = frame.shape + data = {'value': frame.to_numpy().ravel('F'), + 'variable': np.asarray(frame.columns).repeat(N), + 'date': np.tile(np.asarray(frame.index), K)} + columns = ['date', 'variable', 'value'] + return pd.DataFrame(data, columns=columns) df = unpivot(tm.makeTimeDataFrame()) @@ -371,8 +371,8 @@ Consider a data set like this: 'C': ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 4, 'D': np.random.randn(24), 'E': np.random.randn(24), - 'F': [datetime.datetime(2013, i, 1) for i in range(1, 13)] + - [datetime.datetime(2013, i, 15) for i in range(1, 13)]}) + 'F': [datetime.datetime(2013, i, 1) for i in range(1, 13)] + + [datetime.datetime(2013, i, 15) for i in range(1, 13)]}) df We can produce pivot tables from this data very easily: @@ -397,7 +397,8 @@ Also, you can use ``Grouper`` for ``index`` and ``columns`` keywords. For detail .. ipython:: python - pd.pivot_table(df, values='D', index=pd.Grouper(freq='M', key='F'), columns='C') + pd.pivot_table(df, values='D', index=pd.Grouper(freq='M', key='F'), + columns='C') You can render a nice output of the table omitting the missing values by calling ``to_string`` if you wish: @@ -693,6 +694,7 @@ handling of NaN: .. code-block:: ipython + In [1]: x = pd.Series(['A', 'A', np.nan, 'B', 3.14, np.inf]) In [2]: pd.factorize(x, sort=True) Out[2]: (array([ 2, 2, -1, 3, 0, 1]), @@ -721,7 +723,8 @@ DataFrame will be pivoted in the answers below. n = 20 cols = np.array(['key', 'row', 'item', 'col']) - df = cols + pd.DataFrame((np.random.randint(5, size=(n, 4)) // [2, 1, 2, 1]).astype(str)) + df = cols + pd.DataFrame((np.random.randint(5, size=(n, 4)) + // [2, 1, 2, 1]).astype(str)) df.columns = cols df = df.join(pd.DataFrame(np.random.rand(n, 2).round(2)).add_prefix('val')) @@ -734,7 +737,7 @@ Suppose we wanted to pivot ``df`` such that the ``col`` values are columns, ``row`` values are the index, and the mean of ``val0`` are the values? In particular, the resulting DataFrame should look like: -.. code-block:: ipython +.. note:: col col0 col1 col2 col3 col4 row diff --git a/doc/source/tutorials.rst b/doc/source/tutorials.rst index d5da7df347573..c07319fff777b 100644 --- a/doc/source/tutorials.rst +++ b/doc/source/tutorials.rst @@ -1,5 +1,7 @@ .. _tutorials: +{{ header }} + ********* Tutorials ********* diff --git a/doc/source/visualization.rst b/doc/source/visualization.rst index ce3c335b431ad..23207a0e11a65 100644 --- a/doc/source/visualization.rst +++ b/doc/source/visualization.rst @@ -26,7 +26,7 @@ libraries that go beyond the basics documented here. Basic Plotting: ``plot`` ------------------------ -We will demonstrate the basics, see the :ref:`cookbook` for +We will demonstrate the basics, see the :ref:`cookbook` for some advanced strategies. The ``plot`` method on Series and DataFrame is just a simple wrapper around @@ -87,7 +87,7 @@ You can plot one column versus another using the `x` and `y` keywords in .. note:: - For more formatting and styling options, see + For more formatting and styling options, see :ref:`formatting ` below. .. ipython:: python @@ -129,7 +129,7 @@ You can also create these other plots using the methods ``DataFrame.plot.` In [14]: df = pd.DataFrame() - In [15]: df.plot. + In [15]: df.plot. # noqa: E225, E999 df.plot.area df.plot.barh df.plot.density df.plot.hist df.plot.line df.plot.scatter df.plot.bar df.plot.box df.plot.hexbin df.plot.kde df.plot.pie @@ -163,7 +163,8 @@ For labeled, non-time series data, you may wish to produce a bar plot: plt.figure(); @savefig bar_plot_ex.png - df.iloc[5].plot.bar(); plt.axhline(0, color='k') + df.iloc[5].plot.bar() + plt.axhline(0, color='k'); Calling a DataFrame's :meth:`plot.bar() ` method produces a multiple bar plot: @@ -231,7 +232,7 @@ Histograms can be drawn by using the :meth:`DataFrame.plot.hist` and :meth:`Seri plt.close('all') -A histogram can be stacked using ``stacked=True``. Bin size can be changed +A histogram can be stacked using ``stacked=True``. Bin size can be changed using the ``bins`` keyword. .. ipython:: python @@ -246,8 +247,8 @@ using the ``bins`` keyword. plt.close('all') -You can pass other keywords supported by matplotlib ``hist``. For example, -horizontal and cumulative histograms can be drawn by +You can pass other keywords supported by matplotlib ``hist``. For example, +horizontal and cumulative histograms can be drawn by ``orientation='horizontal'`` and ``cumulative=True``. .. ipython:: python @@ -477,7 +478,7 @@ keyword, will affect the output type as well: plt.close('all') -The subplots above are split by the numeric columns first, then the value of +The subplots above are split by the numeric columns first, then the value of the ``g`` column. Below the subplots are first split by the value of ``g``, then by the numeric columns. @@ -579,8 +580,8 @@ each point: plt.close('all') -You can pass other keywords supported by matplotlib -:meth:`scatter `. The example below shows a +You can pass other keywords supported by matplotlib +:meth:`scatter `. The example below shows a bubble chart using a column of the ``DataFrame`` as the bubble size. .. ipython:: python @@ -684,15 +685,15 @@ A ``ValueError`` will be raised if there are any negative values in your data. plt.close('all') -For pie plots it's best to use square figures, i.e. a figure aspect ratio 1. -You can create the figure with equal width and height, or force the aspect ratio -to be equal after plotting by calling ``ax.set_aspect('equal')`` on the returned +For pie plots it's best to use square figures, i.e. a figure aspect ratio 1. +You can create the figure with equal width and height, or force the aspect ratio +to be equal after plotting by calling ``ax.set_aspect('equal')`` on the returned ``axes`` object. -Note that pie plot with :class:`DataFrame` requires that you either specify a -target column by the ``y`` argument or ``subplots=True``. When ``y`` is -specified, pie plot of selected column will be drawn. If ``subplots=True`` is -specified, pie plots for each column are drawn as subplots. A legend will be +Note that pie plot with :class:`DataFrame` requires that you either specify a +target column by the ``y`` argument or ``subplots=True``. When ``y`` is +specified, pie plot of selected column will be drawn. If ``subplots=True`` is +specified, pie plots for each column are drawn as subplots. A legend will be drawn in each pie plots by default; specify ``legend=False`` to hide it. .. ipython:: python @@ -918,7 +919,7 @@ Lag Plot Lag plots are used to check if a data set or time series is random. Random data should not exhibit any structure in the lag plot. Non-random structure implies that the underlying data are not random. The ``lag`` argument may -be passed, and when ``lag=1`` the plot is essentially ``data[:-1]`` vs. +be passed, and when ``lag=1`` the plot is essentially ``data[:-1]`` vs. ``data[1:]``. .. ipython:: python @@ -954,7 +955,7 @@ If time series is random, such autocorrelations should be near zero for any and all time-lag separations. If time series is non-random then one or more of the autocorrelations will be significantly non-zero. The horizontal lines displayed in the plot correspond to 95% and 99% confidence bands. The dashed line is 99% -confidence band. See the +confidence band. See the `Wikipedia entry `__ for more about autocorrelation plots. @@ -1446,9 +1447,9 @@ Plotting with matplotlib table is now supported in :meth:`DataFrame.plot` and : plt.close('all') -Also, you can pass a different :class:`DataFrame` or :class:`Series` to the -``table`` keyword. The data will be drawn as displayed in print method -(not transposed automatically). If required, it should be transposed manually +Also, you can pass a different :class:`DataFrame` or :class:`Series` to the +``table`` keyword. The data will be drawn as displayed in print method +(not transposed automatically). If required, it should be transposed manually as seen in the example below. .. ipython:: python @@ -1463,9 +1464,9 @@ as seen in the example below. plt.close('all') -There also exists a helper function ``pandas.plotting.table``, which creates a -table from :class:`DataFrame` or :class:`Series`, and adds it to an -``matplotlib.Axes`` instance. This function can accept keywords which the +There also exists a helper function ``pandas.plotting.table``, which creates a +table from :class:`DataFrame` or :class:`Series`, and adds it to an +``matplotlib.Axes`` instance. This function can accept keywords which the matplotlib `table `__ has. .. ipython:: python @@ -1597,8 +1598,8 @@ Plotting directly with matplotlib In some situations it may still be preferable or necessary to prepare plots directly with matplotlib, for instance when a certain type of plot or -customization is not (yet) supported by pandas. ``Series`` and ``DataFrame`` -objects behave like arrays and can therefore be passed directly to +customization is not (yet) supported by pandas. ``Series`` and ``DataFrame`` +objects behave like arrays and can therefore be passed directly to matplotlib functions without explicit casts. pandas also automatically registers formatters and locators that recognize date diff --git a/doc/source/whatsnew/v0.22.0.rst b/doc/source/whatsnew/v0.22.0.rst index 1fb87c9f5433f..b38fcd9d62af4 100644 --- a/doc/source/whatsnew/v0.22.0.rst +++ b/doc/source/whatsnew/v0.22.0.rst @@ -137,8 +137,8 @@ sum and ``1`` for product. .. code-block:: ipython In [11]: s = pd.Series([1, 1, np.nan, np.nan], - ...: index=pd.date_range('2017', periods=4)) - ...: s + ....: index=pd.date_range('2017', periods=4)) + ....: s Out[11]: 2017-01-01 1.0 2017-01-02 1.0 diff --git a/doc/source/whatsnew/v0.23.0.rst b/doc/source/whatsnew/v0.23.0.rst index d8eb337fd27d2..e52a36a922bd9 100644 --- a/doc/source/whatsnew/v0.23.0.rst +++ b/doc/source/whatsnew/v0.23.0.rst @@ -53,10 +53,10 @@ A ``DataFrame`` can now be written to and subsequently read back via JSON while .. ipython:: python df = pd.DataFrame({'foo': [1, 2, 3, 4], - 'bar': ['a', 'b', 'c', 'd'], - 'baz': pd.date_range('2018-01-01', freq='d', periods=4), - 'qux': pd.Categorical(['a', 'b', 'c', 'c']) - }, index=pd.Index(range(4), name='idx')) + 'bar': ['a', 'b', 'c', 'd'], + 'baz': pd.date_range('2018-01-01', freq='d', periods=4), + 'qux': pd.Categorical(['a', 'b', 'c', 'c'])}, + index=pd.Index(range(4), name='idx')) df df.dtypes df.to_json('test.json', orient='table') @@ -97,7 +97,7 @@ The :func:`DataFrame.assign` now accepts dependent keyword arguments for python df = pd.DataFrame({'A': [1, 2, 3]}) df - df.assign(B=df.A, C=lambda x:x['A']+ x['B']) + df.assign(B=df.A, C=lambda x: x['A'] + x['B']) .. warning:: @@ -122,7 +122,7 @@ The :func:`DataFrame.assign` now accepts dependent keyword arguments for python .. ipython:: python - df.assign(A=df.A+1, C= lambda df: df.A* -1) + df.assign(A=df.A + 1, C=lambda df: df.A * -1) @@ -284,7 +284,7 @@ For pivotting operations, this behavior is *already* controlled by the ``dropna` categories=["a", "b", "z"], ordered=True) cat2 = pd.Categorical(["c", "d", "c", "d"], categories=["c", "d", "y"], ordered=True) - df = DataFrame({"A": cat1, "B": cat2, "values": [1, 2, 3, 4]}) + df = pd.DataFrame({"A": cat1, "B": cat2, "values": [1, 2, 3, 4]}) df .. ipython:: python @@ -336,7 +336,8 @@ outside the existing valid values while preserving those inside. (:issue:`16284 .. ipython:: python - ser = pd.Series([np.nan, np.nan, 5, np.nan, np.nan, np.nan, 13, np.nan, np.nan]) + ser = pd.Series([np.nan, np.nan, 5, np.nan, np.nan, + np.nan, 13, np.nan, np.nan]) ser Fill one consecutive inside value in both directions @@ -600,15 +601,16 @@ Previous Behavior (and current behavior if on Python < 3.6): .. code-block:: ipython - pd.Series({'Income': 2000, - 'Expenses': -1500, - 'Taxes': -200, - 'Net result': 300}) - Expenses -1500 - Income 2000 - Net result 300 - Taxes -200 - dtype: int64 + In [16]: pd.Series({'Income': 2000, + ....: 'Expenses': -1500, + ....: 'Taxes': -200, + ....: 'Net result': 300}) + Out[16]: + Expenses -1500 + Income 2000 + Net result 300 + Taxes -200 + dtype: int64 Note the Series above is ordered alphabetically by the index values. @@ -696,7 +698,8 @@ where a list-like (e.g. ``tuple`` or ``list`` is returned) (:issue:`16353`, :iss .. ipython:: python - df = pd.DataFrame(np.tile(np.arange(3), 6).reshape(6, -1) + 1, columns=['A', 'B', 'C']) + df = pd.DataFrame(np.tile(np.arange(3), 6).reshape(6, -1) + 1, + columns=['A', 'B', 'C']) df Previous Behavior: if the returned shape happened to match the length of original columns, this would return a ``DataFrame``. @@ -750,7 +753,7 @@ Returning a ``Series`` allows one to control the exact return structure and colu .. ipython:: python - df.apply(lambda x: Series([1, 2, 3], index=['D', 'E', 'F']), axis=1) + df.apply(lambda x: pd.Series([1, 2, 3], index=['D', 'E', 'F']), axis=1) .. _whatsnew_0230.api_breaking.concat: @@ -825,10 +828,12 @@ Current Behavior: .. ipython:: python index = pd.Int64Index([-1, 0, 1]) - # division by zero gives -infinity where negative, +infinity where positive, and NaN for 0 / 0 + # division by zero gives -infinity where negative, + # +infinity where positive, and NaN for 0 / 0 index / 0 - # The result of division by zero should not depend on whether the zero is int or float + # The result of division by zero should not depend on + # whether the zero is int or float index / 0.0 index = pd.UInt64Index([0, 1]) @@ -853,7 +858,7 @@ Previous Behavior: In [1]: s = pd.Series(['number 10', '12 eggs']) - In [2]: extracted = s.str.extract('.*(\d\d).*') + In [2]: extracted = s.str.extract(r'.*(\d\d).*') In [3]: extracted Out [3]: @@ -870,7 +875,7 @@ New Behavior: .. ipython:: python s = pd.Series(['number 10', '12 eggs']) - extracted = s.str.extract('.*(\d\d).*') + extracted = s.str.extract(r'.*(\d\d).*') extracted type(extracted) @@ -879,7 +884,7 @@ To restore previous behavior, simply set ``expand`` to ``False``: .. ipython:: python s = pd.Series(['number 10', '12 eggs']) - extracted = s.str.extract('.*(\d\d).*', expand=False) + extracted = s.str.extract(r'.*(\d\d).*', expand=False) extracted type(extracted) diff --git a/doc/source/whatsnew/v0.23.1.rst b/doc/source/whatsnew/v0.23.1.rst index f8bfced171a7c..f6af2990c935b 100644 --- a/doc/source/whatsnew/v0.23.1.rst +++ b/doc/source/whatsnew/v0.23.1.rst @@ -5,11 +5,6 @@ What's New in 0.23.1 (June 12, 2018) {{ header }} -.. ipython:: python - :suppress: - - from pandas import * # noqa F401, F403 - This is a minor bug-fix release in the 0.23.x series and includes some small regression fixes and bug fixes. We recommend that all users upgrade to this version. @@ -43,19 +38,20 @@ To summarize, here's the behavior in 0.22.0, 0.23.0, 0.23.1: .. code-block:: python # 0.22.0... Silently coerce the datetime.date - >>> Series(pd.date_range('2017', periods=2)) == datetime.date(2017, 1, 1) + >>> import datetime + >>> pd.Series(pd.date_range('2017', periods=2)) == datetime.date(2017, 1, 1) 0 True 1 False dtype: bool # 0.23.0... Do not coerce the datetime.date - >>> Series(pd.date_range('2017', periods=2)) == datetime.date(2017, 1, 1) + >>> pd.Series(pd.date_range('2017', periods=2)) == datetime.date(2017, 1, 1) 0 False 1 False dtype: bool # 0.23.1... Coerce the datetime.date with a warning - >>> Series(pd.date_range('2017', periods=2)) == datetime.date(2017, 1, 1) + >>> pd.Series(pd.date_range('2017', periods=2)) == datetime.date(2017, 1, 1) /bin/python:1: FutureWarning: Comparing Series of datetimes with 'datetime.date'. Currently, the 'datetime.date' is coerced to a datetime. In the future pandas will not coerce, and the values not compare equal to the 'datetime.date'. diff --git a/doc/source/whatsnew/v0.23.2.rst b/doc/source/whatsnew/v0.23.2.rst index 9523724827722..cae2415e3374e 100644 --- a/doc/source/whatsnew/v0.23.2.rst +++ b/doc/source/whatsnew/v0.23.2.rst @@ -5,11 +5,6 @@ What's New in 0.23.2 (July 5, 2018) {{ header }} -.. ipython:: python - :suppress: - - from pandas import * # noqa F401, F403 - This is a minor bug-fix release in the 0.23.x series and includes some small regression fixes and bug fixes. We recommend that all users upgrade to this version. diff --git a/doc/source/whatsnew/v0.23.4.rst b/doc/source/whatsnew/v0.23.4.rst index 75fb18a648d0a..01f904e129f80 100644 --- a/doc/source/whatsnew/v0.23.4.rst +++ b/doc/source/whatsnew/v0.23.4.rst @@ -5,11 +5,6 @@ What's New in 0.23.4 (August 3, 2018) {{ header }} -.. ipython:: python - :suppress: - - from pandas import * # noqa F401, F403 - This is a minor bug-fix release in the 0.23.x series and includes some small regression fixes and bug fixes. We recommend that all users upgrade to this version. diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 4c78fcb76f4c6..4d0373e4571da 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -10,11 +10,6 @@ What's New in 0.24.0 (Month XX, 2018) {{ header }} -.. ipython:: python - :suppress: - - from pandas import * # noqa F401, F403 - These are the changes in pandas 0.24.0. See :ref:`release` for a full changelog including other versions of pandas. @@ -252,7 +247,7 @@ convenient way to apply users' predefined styling functions, and can help reduce .. ipython:: python - df = pandas.DataFrame({'N': [1250, 1500, 1750], 'X': [0.25, 0.35, 0.50]}) + df = pd.DataFrame({'N': [1250, 1500, 1750], 'X': [0.25, 0.35, 0.50]}) def format_and_align(styler): return (styler.format({'N': '{:,}', 'X': '{:.1%}'}) @@ -282,8 +277,7 @@ See the :ref:`Merge, join, and concatenate left = pd.DataFrame({'A': ['A0', 'A1', 'A2'], - 'B': ['B0', 'B1', 'B2']}, - index=index_left) + 'B': ['B0', 'B1', 'B2']}, index=index_left) index_right = pd.MultiIndex.from_tuples([('K0', 'Y0'), ('K1', 'Y1'), @@ -292,11 +286,9 @@ See the :ref:`Merge, join, and concatenate right = pd.DataFrame({'C': ['C0', 'C1', 'C2', 'C3'], - 'D': ['D0', 'D1', 'D2', 'D3']}, - index=index_right) + 'D': ['D0', 'D1', 'D2', 'D3']}, index=index_right) - - left.join(right) + left.join(right) For earlier versions this can be done using the following. @@ -441,26 +433,26 @@ Previous Behavior on Windows: .. code-block:: ipython - In [1]: data = pd.DataFrame({ - ...: "string_with_lf": ["a\nbc"], - ...: "string_with_crlf": ["a\r\nbc"] - ...: }) + In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"], + ...: "string_with_crlf": ["a\r\nbc"]}) - In [2]: # When passing file PATH to to_csv, line_terminator does not work, and csv is saved with '\r\n'. - ...: # Also, this converts all '\n's in the data to '\r\n'. - ...: data.to_csv("test.csv", index=False, line_terminator='\n') + In [2]: # When passing file PATH to to_csv, + ...: # line_terminator does not work, and csv is saved with '\r\n'. + ...: # Also, this converts all '\n's in the data to '\r\n'. + ...: data.to_csv("test.csv", index=False, line_terminator='\n') In [3]: with open("test.csv", mode='rb') as f: - ...: print(f.read()) - b'string_with_lf,string_with_crlf\r\n"a\r\nbc","a\r\r\nbc"\r\n' + ...: print(f.read()) + Out[3]: b'string_with_lf,string_with_crlf\r\n"a\r\nbc","a\r\r\nbc"\r\n' - In [4]: # When passing file OBJECT with newline option to to_csv, line_terminator works. - ...: with open("test2.csv", mode='w', newline='\n') as f: - ...: data.to_csv(f, index=False, line_terminator='\n') + In [4]: # When passing file OBJECT with newline option to + ...: # to_csv, line_terminator works. + ...: with open("test2.csv", mode='w', newline='\n') as f: + ...: data.to_csv(f, index=False, line_terminator='\n') In [5]: with open("test2.csv", mode='rb') as f: - ...: print(f.read()) - b'string_with_lf,string_with_crlf\n"a\nbc","a\r\nbc"\n' + ...: print(f.read()) + Out[5]: b'string_with_lf,string_with_crlf\n"a\nbc","a\r\nbc"\n' New Behavior on Windows: @@ -471,16 +463,14 @@ New Behavior on Windows: .. code-block:: ipython - In [1]: data = pd.DataFrame({ - ...: "string_with_lf": ["a\nbc"], - ...: "string_with_crlf": ["a\r\nbc"] - ...: }) + In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"], + ...: "string_with_crlf": ["a\r\nbc"]}) In [2]: data.to_csv("test.csv", index=False, line_terminator='\n') In [3]: with open("test.csv", mode='rb') as f: - ...: print(f.read()) - b'string_with_lf,string_with_crlf\n"a\nbc","a\r\nbc"\n' + ...: print(f.read()) + Out[3]: b'string_with_lf,string_with_crlf\n"a\nbc","a\r\nbc"\n' - On Windows, the value of ``os.linesep`` is ``'\r\n'``, @@ -489,16 +479,14 @@ New Behavior on Windows: .. code-block:: ipython - In [1]: data = pd.DataFrame({ - ...: "string_with_lf": ["a\nbc"], - ...: "string_with_crlf": ["a\r\nbc"] - ...: }) + In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"], + ...: "string_with_crlf": ["a\r\nbc"]}) In [2]: data.to_csv("test.csv", index=False) In [3]: with open("test.csv", mode='rb') as f: - ...: print(f.read()) - b'string_with_lf,string_with_crlf\r\n"a\nbc","a\r\nbc"\r\n' + ...: print(f.read()) + Out[3]: b'string_with_lf,string_with_crlf\r\n"a\nbc","a\r\nbc"\r\n' - For files objects, specifying ``newline`` is not sufficient to set the line terminator. @@ -506,17 +494,15 @@ New Behavior on Windows: .. code-block:: ipython - In [1]: data = pd.DataFrame({ - ...: "string_with_lf": ["a\nbc"], - ...: "string_with_crlf": ["a\r\nbc"] - ...: }) + In [1]: data = pd.DataFrame({"string_with_lf": ["a\nbc"], + ...: "string_with_crlf": ["a\r\nbc"]}) In [2]: with open("test2.csv", mode='w', newline='\n') as f: - ...: data.to_csv(f, index=False) + ...: data.to_csv(f, index=False) In [3]: with open("test2.csv", mode='rb') as f: - ...: print(f.read()) - b'string_with_lf,string_with_crlf\r\n"a\nbc","a\r\nbc"\r\n' + ...: print(f.read()) + Out[3]: b'string_with_lf,string_with_crlf\r\n"a\nbc","a\r\nbc"\r\n' .. _whatsnew_0240.api.timezone_offset_parsing: @@ -563,7 +549,8 @@ Parsing datetime strings with different UTC offsets will now create an Index of .. ipython:: python - idx = pd.to_datetime(["2015-11-18 15:30:00+05:30", "2015-11-18 16:30:00+06:30"]) + idx = pd.to_datetime(["2015-11-18 15:30:00+05:30", + "2015-11-18 16:30:00+06:30"]) idx idx[0] idx[1] @@ -573,7 +560,8 @@ that the dates have been converted to UTC .. ipython:: python - pd.to_datetime(["2015-11-18 15:30:00+05:30", "2015-11-18 16:30:00+06:30"], utc=True) + pd.to_datetime(["2015-11-18 15:30:00+05:30", + "2015-11-18 16:30:00+06:30"], utc=True) .. _whatsnew_0240.api_breaking.calendarday: @@ -675,6 +663,7 @@ changes were made: - ``SparseDataFrame.combine`` and ``DataFrame.combine_first`` no longer supports combining a sparse column with a dense column while preserving the sparse subtype. The result will be an object-dtype SparseArray. - Setting :attr:`SparseArray.fill_value` to a fill value with a different dtype is now allowed. - ``DataFrame[column]`` is now a :class:`Series` with sparse values, rather than a :class:`SparseSeries`, when slicing a single column with sparse values (:issue:`23559`). +- The result of :meth:`Series.where` is now a ``Series`` with sparse values, like with other extension arrays (:issue:`24077`) Some new warnings are issued for operations that require or are likely to materialize a large dense array: @@ -844,7 +833,7 @@ Previous Behavior: In [4]: df = pd.DataFrame(arr) In [5]: df == arr[[0], :] - ...: # comparison previously broadcast where arithmetic would raise + ...: # comparison previously broadcast where arithmetic would raise Out[5]: 0 1 0 True True @@ -855,8 +844,8 @@ Previous Behavior: ValueError: Unable to coerce to DataFrame, shape must be (3, 2): given (1, 2) In [7]: df == (1, 2) - ...: # length matches number of columns; - ...: # comparison previously raised where arithmetic would broadcast + ...: # length matches number of columns; + ...: # comparison previously raised where arithmetic would broadcast ... ValueError: Invalid broadcasting comparison [(1, 2)] with block values In [8]: df + (1, 2) @@ -867,8 +856,8 @@ Previous Behavior: 2 5 7 In [9]: df == (1, 2, 3) - ...: # length matches number of rows - ...: # comparison previously broadcast where arithmetic would raise + ...: # length matches number of rows + ...: # comparison previously broadcast where arithmetic would raise Out[9]: 0 1 0 False True @@ -1031,7 +1020,8 @@ Current Behavior: .. code-block:: ipython - In [3]: df = pd.DataFrame({'a': [1, 2, 2, 2, 2], 'b': [3, 3, 4, 4, 4], + In [3]: df = pd.DataFrame({'a': [1, 2, 2, 2, 2], + ...: 'b': [3, 3, 4, 4, 4], ...: 'c': [1, 1, np.nan, 1, 1]}) In [4]: pd.crosstab(df.a, df.b, normalize='columns') @@ -1113,6 +1103,9 @@ Deprecations - :func:`pandas.types.is_datetimetz` is deprecated in favor of `pandas.types.is_datetime64tz` (:issue:`23917`) - Creating a :class:`TimedeltaIndex` or :class:`DatetimeIndex` by passing range arguments `start`, `end`, and `periods` is deprecated in favor of :func:`timedelta_range` and :func:`date_range` (:issue:`23919`) - Passing a string alias like ``'datetime64[ns, UTC]'`` as the `unit` parameter to :class:`DatetimeTZDtype` is deprecated. Use :class:`DatetimeTZDtype.construct_from_string` instead (:issue:`23990`). +- In :meth:`Series.where` with Categorical data, providing an ``other`` that is not present in the categories is deprecated. Convert the categorical to a different dtype or add the ``other`` to the categories first (:issue:`24077`). +- :meth:`Series.clip_lower`, :meth:`Series.clip_upper`, :meth:`DataFrame.clip_lower` and :meth:`DataFrame.clip_upper` are deprecated and will be removed in a future version. Use ``Series.clip(lower=threshold)``, ``Series.clip(upper=threshold)`` and the equivalent ``DataFrame`` methods (:issue:`24203`) + .. _whatsnew_0240.deprecations.datetimelike_int_ops: @@ -1209,6 +1202,7 @@ Performance Improvements - Improved performance of :func:`Series.describe` in case of numeric dtpyes (:issue:`21274`) - Improved performance of :func:`pandas.core.groupby.GroupBy.rank` when dealing with tied rankings (:issue:`21237`) - Improved performance of :func:`DataFrame.set_index` with columns consisting of :class:`Period` objects (:issue:`21582`, :issue:`21606`) +- Improved performance of :meth:`Series.at` and :meth:`Index.get_value` for Extension Arrays values (e.g. :class:`Categorical`) (:issue:`24204`) - Improved performance of membership checks in :class:`Categorical` and :class:`CategoricalIndex` (i.e. ``x in cat``-style checks are much faster). :meth:`CategoricalIndex.contains` is likewise much faster (:issue:`21369`, :issue:`21508`) @@ -1223,6 +1217,7 @@ Performance Improvements - Improved performance of :meth:`DatetimeIndex.tz_localize` and various ``DatetimeIndex`` attributes with dateutil UTC timezone (:issue:`23772`) - Fixed a performance regression on Windows with Python 3.7 of :func:`pd.read_csv` (:issue:`23516`) - Improved performance of :class:`Categorical` constructor for `Series` objects (:issue:`23814`) +- Improved performance of :meth:`~DataFrame.where` for Categorical data (:issue:`24077`) .. _whatsnew_0240.docs: @@ -1249,6 +1244,7 @@ Categorical - In meth:`Series.unstack`, specifying a ``fill_value`` not present in the categories now raises a ``TypeError`` rather than ignoring the ``fill_value`` (:issue:`23284`) - Bug when resampling :meth:`Dataframe.resample()` and aggregating on categorical data, the categorical dtype was getting lost. (:issue:`23227`) - Bug in many methods of the ``.str``-accessor, which always failed on calling the ``CategoricalIndex.str`` constructor (:issue:`23555`, :issue:`23556`) +- Bug in :meth:`Series.where` losing the categorical dtype for categorical data (:issue:`24077`) Datetimelike ^^^^^^^^^^^^ @@ -1285,6 +1281,8 @@ Datetimelike - Bug in :class:`DatetimeIndex` where calling ``np.array(dtindex, dtype=object)`` would incorrectly return an array of ``long`` objects (:issue:`23524`) - Bug in :class:`Index` where passing a timezone-aware :class:`DatetimeIndex` and `dtype=object` would incorrectly raise a ``ValueError`` (:issue:`23524`) - Bug in :class:`Index` where calling ``np.array(dtindex, dtype=object)`` on a timezone-naive :class:`DatetimeIndex` would return an array of ``datetime`` objects instead of :class:`Timestamp` objects, potentially losing nanosecond portions of the timestamps (:issue:`23524`) +- Bug in :class:`Categorical.__setitem__` not allowing setting with another ``Categorical`` when both are undordered and have the same categories, but in a different order (:issue:`24142`) +- Bug in :func:`date_range` where using dates with millisecond resolution or higher could return incorrect values or the wrong number of values in the index (:issue:`24110`) Timedelta ^^^^^^^^^ @@ -1355,6 +1353,7 @@ Numeric - :meth:`Series.agg` can now handle numpy NaN-aware methods like :func:`numpy.nansum` (:issue:`19629`) - Bug in :meth:`Series.rank` and :meth:`DataFrame.rank` when ``pct=True`` and more than 2:sup:`24` rows are present resulted in percentages greater than 1.0 (:issue:`18271`) - Calls such as :meth:`DataFrame.round` with a non-unique :meth:`CategoricalIndex` now return expected data. Previously, data would be improperly duplicated (:issue:`21809`). +- Added ``log10`` to the list of supported functions in :meth:`DataFrame.eval` (:issue:`24139`) Strings ^^^^^^^ diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index b4862a5f3b02f..472ac0ee6d45c 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -import enum import warnings from cpython cimport (PyObject_RichCompareBool, PyObject_RichCompare, @@ -71,8 +70,7 @@ cdef inline object create_timestamp_from_ts(int64_t value, return ts_base -@enum.unique -class RoundTo(enum.Enum): +class RoundTo(object): """ enumeration defining the available rounding modes @@ -105,11 +103,25 @@ class RoundTo(enum.Enum): .. [6] "Round half to even" https://en.wikipedia.org/wiki/Rounding#Round_half_to_even """ - MINUS_INFTY = 0 - PLUS_INFTY = 1 - NEAREST_HALF_EVEN = 2 - NEAREST_HALF_PLUS_INFTY = 3 - NEAREST_HALF_MINUS_INFTY = 4 + @property + def MINUS_INFTY(self): + return 0 + + @property + def PLUS_INFTY(self): + return 1 + + @property + def NEAREST_HALF_EVEN(self): + return 2 + + @property + def NEAREST_HALF_PLUS_INFTY(self): + return 3 + + @property + def NEAREST_HALF_MINUS_INFTY(self): + return 4 cdef inline _npdivmod(x1, x2): @@ -152,20 +164,17 @@ def round_nsint64(values, mode, freq): :obj:`ndarray` """ - if not isinstance(mode, RoundTo): - raise ValueError('mode should be a RoundTo member') - unit = to_offset(freq).nanos - if mode is RoundTo.MINUS_INFTY: + if mode == RoundTo.MINUS_INFTY: return _floor_int64(values, unit) - elif mode is RoundTo.PLUS_INFTY: + elif mode == RoundTo.PLUS_INFTY: return _ceil_int64(values, unit) - elif mode is RoundTo.NEAREST_HALF_MINUS_INFTY: + elif mode == RoundTo.NEAREST_HALF_MINUS_INFTY: return _rounddown_int64(values, unit) - elif mode is RoundTo.NEAREST_HALF_PLUS_INFTY: + elif mode == RoundTo.NEAREST_HALF_PLUS_INFTY: return _roundup_int64(values, unit) - elif mode is RoundTo.NEAREST_HALF_EVEN: + elif mode == RoundTo.NEAREST_HALF_EVEN: # for odd unit there is no need of a tie break if unit % 2: return _rounddown_int64(values, unit) @@ -179,8 +188,8 @@ def round_nsint64(values, mode, freq): # if/elif above should catch all rounding modes defined in enum 'RoundTo': # if flow of control arrives here, it is a bug - raise AssertionError("round_nsint64 called with an unrecognized " - "rounding mode") + raise ValueError("round_nsint64 called with an unrecognized " + "rounding mode") # This is PITA. Because we inherit from datetime, which has very specific diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index 15abffa9a5d23..cf145064fd7b1 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -220,6 +220,8 @@ def __setitem__(self, key, value): # example, a string like '2018-01-01' is coerced to a datetime # when setting on a datetime64ns array. In general, if the # __init__ method coerces that value, then so should __setitem__ + # Note, also, that Series/DataFrame.where internally use __setitem__ + # on a copy of the data. raise NotImplementedError(_not_implemented_message.format( type(self), '__setitem__') ) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index b2c580ac435db..101d03cd55d40 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2078,11 +2078,21 @@ def __setitem__(self, key, value): `Categorical` does not have the same categories """ + if isinstance(value, (ABCIndexClass, ABCSeries)): + value = value.array + # require identical categories set if isinstance(value, Categorical): - if not value.categories.equals(self.categories): + if not is_dtype_equal(self, value): raise ValueError("Cannot set a Categorical with another, " "without identical categories") + if not self.categories.equals(value.categories): + new_codes = _recode_for_categories( + value.codes, value.categories, self.categories + ) + value = Categorical.from_codes(new_codes, + categories=self.categories, + ordered=self.ordered) rvalue = value if is_list_like(value) else [value] diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 9e8116bd15611..4849ee1e3e665 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -82,7 +82,7 @@ def f(self): return result f.__name__ = name - f.__doc__ = "{}".format(docstring) + f.__doc__ = "\n{}\n".format(docstring) return property(f) @@ -307,7 +307,12 @@ def _generate_range(cls, start, end, periods, freq, tz=None, end = end.tz_localize(tz).asm8 else: # Create a linearly spaced date_range in local time - arr = np.linspace(start.value, end.value, periods) + # Nanosecond-granularity timestamps aren't always correctly + # representable with doubles, so we limit the range that we + # pass to np.linspace as much as possible + arr = np.linspace( + 0, end.value - start.value, + periods, dtype='int64') + start.value index = cls._simple_new( arr.astype('M8[ns]', copy=False), freq=None, tz=tz ) @@ -1065,9 +1070,9 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', " The year of the datetime.") + year = _field_accessor('year', 'Y', "The year of the datetime.") month = _field_accessor('month', 'M', - " The month as January=1, December=12. ") + "The month as January=1, December=12. ") day = _field_accessor('day', 'D', "The days of the datetime.") hour = _field_accessor('hour', 'h', "The hours of the datetime.") minute = _field_accessor('minute', 'm', "The minutes of the datetime.") diff --git a/pandas/core/arrays/sparse.py b/pandas/core/arrays/sparse.py index 0bd899149d940..9e1d2efc21b81 100644 --- a/pandas/core/arrays/sparse.py +++ b/pandas/core/arrays/sparse.py @@ -706,6 +706,8 @@ def __array__(self, dtype=None, copy=True): def __setitem__(self, key, value): # I suppose we could allow setting of non-fill_value elements. + # TODO(SparseArray.__setitem__): remove special cases in + # ExtensionBlock.where msg = "SparseArray does not support item assignment via setitem" raise TypeError(msg) diff --git a/pandas/core/computation/ops.py b/pandas/core/computation/ops.py index 9e9f124352229..cbdb3525d5e88 100644 --- a/pandas/core/computation/ops.py +++ b/pandas/core/computation/ops.py @@ -23,7 +23,7 @@ _unary_math_ops = ('sin', 'cos', 'exp', 'log', 'expm1', 'log1p', 'sqrt', 'sinh', 'cosh', 'tanh', 'arcsin', 'arccos', - 'arctan', 'arccosh', 'arcsinh', 'arctanh', 'abs') + 'arctan', 'arccosh', 'arcsinh', 'arctanh', 'abs', 'log10') _binary_math_ops = ('arctan2',) _mathops = _unary_math_ops + _binary_math_ops diff --git a/pandas/core/generic.py b/pandas/core/generic.py index e52a0b60c610e..11d1333851794 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -7206,11 +7206,6 @@ def clip(self, lower=None, upper=None, axis=None, inplace=False, Same type as calling object with the values outside the clip boundaries replaced - See Also - -------- - clip_lower : Clip values below specified threshold(s). - clip_upper : Clip values above specified threshold(s). - Examples -------- >>> data = {'col_0': [9, -3, 0, -1, 5], 'col_1': [-2, -7, 6, 8, -5]} @@ -7283,11 +7278,13 @@ def clip(self, lower=None, upper=None, axis=None, inplace=False, result = self if lower is not None: - result = result.clip_lower(lower, axis, inplace=inplace) + result = result._clip_with_one_bound(lower, method=self.ge, + axis=axis, inplace=inplace) if upper is not None: if inplace: result = self - result = result.clip_upper(upper, axis, inplace=inplace) + result = result._clip_with_one_bound(upper, method=self.le, + axis=axis, inplace=inplace) return result @@ -7295,6 +7292,9 @@ def clip_upper(self, threshold, axis=None, inplace=False): """ Trim values above a given threshold. + .. deprecated:: 0.24.0 + Use clip(upper=threshold) instead. + Elements above the `threshold` will be changed to match the `threshold` value(s). Threshold can be a single value or an array, in the latter case it performs the truncation element-wise. @@ -7321,18 +7321,15 @@ def clip_upper(self, threshold, axis=None, inplace=False): Returns ------- - clipped + Series or DataFrame Original data with values trimmed. See Also -------- - DataFrame.clip : General purpose method to trim DataFrame values to - given threshold(s). - DataFrame.clip_lower : Trim DataFrame values below given - threshold(s). Series.clip : General purpose method to trim Series values to given threshold(s). - Series.clip_lower : Trim Series values below given threshold(s). + DataFrame.clip : General purpose method to trim DataFrame values to + given threshold(s). Examples -------- @@ -7365,6 +7362,9 @@ def clip_upper(self, threshold, axis=None, inplace=False): 4 1 dtype: int64 """ + warnings.warn('clip_upper(threshold) is deprecated, ' + 'use clip(upper=threshold) instead', + FutureWarning, stacklevel=2) return self._clip_with_one_bound(threshold, method=self.le, axis=axis, inplace=inplace) @@ -7372,6 +7372,9 @@ def clip_lower(self, threshold, axis=None, inplace=False): """ Trim values below a given threshold. + .. deprecated:: 0.24.0 + Use clip(lower=threshold) instead. + Elements below the `threshold` will be changed to match the `threshold` value(s). Threshold can be a single value or an array, in the latter case it performs the truncation element-wise. @@ -7399,18 +7402,15 @@ def clip_lower(self, threshold, axis=None, inplace=False): Returns ------- - clipped + Series or DataFrame Original data with values trimmed. See Also -------- - DataFrame.clip : General purpose method to trim DataFrame values to - given threshold(s). - DataFrame.clip_upper : Trim DataFrame values above given - threshold(s). Series.clip : General purpose method to trim Series values to given threshold(s). - Series.clip_upper : Trim Series values above given threshold(s). + DataFrame.clip : General purpose method to trim DataFrame values to + given threshold(s). Examples -------- @@ -7478,6 +7478,9 @@ def clip_lower(self, threshold, axis=None, inplace=False): 1 4 5 2 5 6 """ + warnings.warn('clip_lower(threshold) is deprecated, ' + 'use clip(lower=threshold) instead', + FutureWarning, stacklevel=2) return self._clip_with_one_bound(threshold, method=self.ge, axis=axis, inplace=inplace) @@ -9896,11 +9899,11 @@ def _add_numeric_operations(cls): axis_descr, name, name2 = _doc_parms(cls) cls.any = _make_logical_function( - cls, 'any', name, name2, axis_descr, - _any_desc, nanops.nanany, _any_examples, _any_see_also) + cls, 'any', name, name2, axis_descr, _any_desc, nanops.nanany, + _any_examples, _any_see_also, empty_value=False) cls.all = _make_logical_function( - cls, 'all', name, name2, axis_descr, _all_doc, - nanops.nanall, _all_examples, _all_see_also) + cls, 'all', name, name2, axis_descr, _all_desc, nanops.nanall, + _all_examples, _all_see_also, empty_value=True) @Substitution(outname='mad', desc="Return the mean absolute deviation of the values " @@ -10221,12 +10224,14 @@ def _doc_parms(cls): original index. * None : reduce all axes, return a scalar. -bool_only : boolean, default None +bool_only : bool, default None Include only boolean columns. If None, will attempt to use everything, then use only boolean data. Not implemented for Series. -skipna : boolean, default True - Exclude NA/null values. If an entire row/column is NA, the result - will be NA. +skipna : bool, default True + Exclude NA/null values. If the entire row/column is NA and skipna is + True, then the result will be %(empty_value)s, as for an empty row/column. + If skipna is False, then NA are treated as True, because these are not + equal to zero. level : int or level name, default None If the axis is a MultiIndex (hierarchical), count along a particular level, collapsing into a %(name1)s. @@ -10236,28 +10241,37 @@ def _doc_parms(cls): Returns ------- -%(outname)s : %(name1)s or %(name2)s (if level specified) +%(name1)s or %(name2)s + If level is specified, then, %(name2)s is returned; otherwise, %(name1)s + is returned. %(see_also)s %(examples)s""" -_all_doc = """\ +_all_desc = """\ Return whether all elements are True, potentially over an axis. -Returns True if all elements within a series or along a Dataframe -axis are non-zero, not-empty or not-False.""" +Returns True unless there at least one element within a series or +along a Dataframe axis that is False or equivalent (e.g. zero or +empty).""" _all_examples = """\ Examples -------- -Series +**Series** >>> pd.Series([True, True]).all() True >>> pd.Series([True, False]).all() False +>>> pd.Series([]).all() +True +>>> pd.Series([np.nan]).all() +True +>>> pd.Series([np.nan]).all(skipna=False) +True -DataFrames +**DataFrames** Create a dataframe from a dictionary. @@ -10599,10 +10613,11 @@ def _doc_parms(cls): """ _any_desc = """\ -Return whether any element is True over requested axis. +Return whether any element is True, potentially over an axis. -Unlike :meth:`DataFrame.all`, this performs an *or* operation. If any of the -values along the specified axis is True, this will return True.""" +Returns False unless there at least one element within a series or +along a Dataframe axis that is True or equivalent (e.g. non-zero or +non-empty).""" _any_examples = """\ Examples @@ -10612,8 +10627,16 @@ def _doc_parms(cls): For Series input, the output is a scalar indicating whether any element is True. +>>> pd.Series([False, False]).any() +False >>> pd.Series([True, False]).any() True +>>> pd.Series([]).any() +False +>>> pd.Series([np.nan]).any() +False +>>> pd.Series([np.nan]).any(skipna=False) +True **DataFrame** @@ -10899,9 +10922,10 @@ def cum_func(self, axis=None, skipna=True, *args, **kwargs): def _make_logical_function(cls, name, name1, name2, axis_descr, desc, f, - examples, see_also): + examples, see_also, empty_value): @Substitution(outname=name, desc=desc, name1=name1, name2=name2, - axis_descr=axis_descr, examples=examples, see_also=see_also) + axis_descr=axis_descr, examples=examples, see_also=see_also, + empty_value=empty_value) @Appender(_bool_doc) def logical_func(self, axis=0, bool_only=None, skipna=True, level=None, **kwargs): diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index fc5f6758f9e06..811d66c74ed15 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4281,7 +4281,8 @@ def get_value(self, series, key): # if we have something that is Index-like, then # use this, e.g. DatetimeIndex - s = getattr(series, '_values', None) + # Things like `Series._get_value` (via .at) pass the EA directly here. + s = getattr(series, '_values', series) if isinstance(s, (ExtensionArray, Index)) and is_scalar(key): # GH 20882, 21257 # Unify Index and ExtensionArray treatment diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index 9ce4949992f4c..f1a05ec607b59 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -501,10 +501,13 @@ def _can_reindex(self, indexer): @Appender(_index_shared_docs['where']) def where(self, cond, other=None): + # TODO: Investigate an alternative implementation with + # 1. copy the underyling Categorical + # 2. setitem with `cond` and `other` + # 3. Rebuild CategoricalIndex. if other is None: other = self._na_value values = np.where(cond, self.values, other) - cat = Categorical(values, dtype=self.dtype) return self._shallow_copy(cat, **self._get_attributes_dict()) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index d37da14ab5d2c..1383ce09bc2d0 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -28,7 +28,8 @@ from pandas.core.dtypes.dtypes import ( CategoricalDtype, DatetimeTZDtype, ExtensionDtype, PandasExtensionDtype) from pandas.core.dtypes.generic import ( - ABCDatetimeIndex, ABCExtensionArray, ABCIndexClass, ABCSeries) + ABCDataFrame, ABCDatetimeIndex, ABCExtensionArray, ABCIndexClass, + ABCSeries) from pandas.core.dtypes.missing import ( _isna_compat, array_equivalent, is_null_datelike_scalar, isna, notna) @@ -1886,7 +1887,6 @@ def take_nd(self, indexer, axis=0, new_mgr_locs=None, fill_tuple=None): new_values = self.values.take(indexer, fill_value=fill_value, allow_fill=True) - # if we are a 1-dim object, then always place at 0 if self.ndim == 1 and new_mgr_locs is None: new_mgr_locs = [0] else: @@ -1967,6 +1967,57 @@ def shift(self, periods, axis=0): placement=self.mgr_locs, ndim=self.ndim)] + def where(self, other, cond, align=True, errors='raise', + try_cast=False, axis=0, transpose=False): + # Extract the underlying arrays. + if isinstance(other, (ABCIndexClass, ABCSeries)): + other = other.array + + elif isinstance(other, ABCDataFrame): + # ExtensionArrays are 1-D, so if we get here then + # `other` should be a DataFrame with a single column. + assert other.shape[1] == 1 + other = other.iloc[:, 0].array + + if isinstance(cond, ABCDataFrame): + assert cond.shape[1] == 1 + cond = cond.iloc[:, 0].array + + elif isinstance(cond, (ABCIndexClass, ABCSeries)): + cond = cond.array + + if lib.is_scalar(other) and isna(other): + # The default `other` for Series / Frame is np.nan + # we want to replace that with the correct NA value + # for the type + other = self.dtype.na_value + + if is_sparse(self.values): + # TODO(SparseArray.__setitem__): remove this if condition + # We need to re-infer the type of the data after doing the + # where, for cases where the subtypes don't match + dtype = None + else: + dtype = self.dtype + + try: + result = self.values.copy() + icond = ~cond + if lib.is_scalar(other): + result[icond] = other + else: + result[icond] = other[icond] + except (NotImplementedError, TypeError): + # NotImplementedError for class not implementing `__setitem__` + # TypeError for SparseArray, which implements just to raise + # a TypeError + result = self._holder._from_sequence( + np.where(cond, self.values, other), + dtype=dtype, + ) + + return self.make_block_same_class(result, placement=self.mgr_locs) + @property def _ftype(self): return getattr(self.values, '_pandas_ftype', Block._ftype) @@ -2658,6 +2709,33 @@ def concat_same_type(self, to_concat, placement=None): values, placement=placement or slice(0, len(values), 1), ndim=self.ndim) + def where(self, other, cond, align=True, errors='raise', + try_cast=False, axis=0, transpose=False): + # TODO(CategoricalBlock.where): + # This can all be deleted in favor of ExtensionBlock.where once + # we enforce the deprecation. + object_msg = ( + "Implicitly converting categorical to object-dtype ndarray. " + "One or more of the values in 'other' are not present in this " + "categorical's categories. A future version of pandas will raise " + "a ValueError when 'other' contains different categories.\n\n" + "To preserve the current behavior, add the new categories to " + "the categorical before calling 'where', or convert the " + "categorical to a different dtype." + ) + try: + # Attempt to do preserve categorical dtype. + result = super(CategoricalBlock, self).where( + other, cond, align, errors, try_cast, axis, transpose + ) + except (TypeError, ValueError): + warnings.warn(object_msg, FutureWarning, stacklevel=6) + result = self.astype(object).where(other, cond, align=align, + errors=errors, + try_cast=try_cast, + axis=axis, transpose=transpose) + return result + class DatetimeBlock(DatetimeLikeBlockMixin, Block): __slots__ = () diff --git a/pandas/tests/arrays/categorical/test_indexing.py b/pandas/tests/arrays/categorical/test_indexing.py index 8df5728f7d895..4ba934f44a0ac 100644 --- a/pandas/tests/arrays/categorical/test_indexing.py +++ b/pandas/tests/arrays/categorical/test_indexing.py @@ -3,6 +3,7 @@ import numpy as np import pytest +import pandas as pd from pandas import Categorical, CategoricalIndex, Index, PeriodIndex, Series import pandas.core.common as com from pandas.tests.arrays.categorical.common import TestCategorical @@ -43,6 +44,45 @@ def test_setitem(self): tm.assert_categorical_equal(c, expected) + @pytest.mark.parametrize('other', [ + pd.Categorical(['b', 'a']), + pd.Categorical(['b', 'a'], categories=['b', 'a']), + ]) + def test_setitem_same_but_unordered(self, other): + # GH-24142 + target = pd.Categorical(['a', 'b'], categories=['a', 'b']) + mask = np.array([True, False]) + target[mask] = other[mask] + expected = pd.Categorical(['b', 'b'], categories=['a', 'b']) + tm.assert_categorical_equal(target, expected) + + @pytest.mark.parametrize('other', [ + pd.Categorical(['b', 'a'], categories=['b', 'a', 'c']), + pd.Categorical(['b', 'a'], categories=['a', 'b', 'c']), + pd.Categorical(['a', 'a'], categories=['a']), + pd.Categorical(['b', 'b'], categories=['b']), + ]) + def test_setitem_different_unordered_raises(self, other): + # GH-24142 + target = pd.Categorical(['a', 'b'], categories=['a', 'b']) + mask = np.array([True, False]) + with pytest.raises(ValueError): + target[mask] = other[mask] + + @pytest.mark.parametrize('other', [ + pd.Categorical(['b', 'a']), + pd.Categorical(['b', 'a'], categories=['b', 'a'], ordered=True), + pd.Categorical(['b', 'a'], categories=['a', 'b', 'c'], ordered=True), + ]) + def test_setitem_same_ordered_rasies(self, other): + # Gh-24142 + target = pd.Categorical(['a', 'b'], categories=['a', 'b'], + ordered=True) + mask = np.array([True, False]) + + with pytest.raises(ValueError): + target[mask] = other[mask] + class TestCategoricalIndexing(object): @@ -122,6 +162,60 @@ def test_get_indexer_non_unique(self, idx_values, key_values, key_class): tm.assert_numpy_array_equal(expected, result) tm.assert_numpy_array_equal(exp_miss, res_miss) + def test_where_unobserved_nan(self): + ser = pd.Series(pd.Categorical(['a', 'b'])) + result = ser.where([True, False]) + expected = pd.Series(pd.Categorical(['a', None], + categories=['a', 'b'])) + tm.assert_series_equal(result, expected) + + # all NA + ser = pd.Series(pd.Categorical(['a', 'b'])) + result = ser.where([False, False]) + expected = pd.Series(pd.Categorical([None, None], + categories=['a', 'b'])) + tm.assert_series_equal(result, expected) + + def test_where_unobserved_categories(self): + ser = pd.Series( + Categorical(['a', 'b', 'c'], categories=['d', 'c', 'b', 'a']) + ) + result = ser.where([True, True, False], other='b') + expected = pd.Series( + Categorical(['a', 'b', 'b'], categories=ser.cat.categories) + ) + tm.assert_series_equal(result, expected) + + def test_where_other_categorical(self): + ser = pd.Series( + Categorical(['a', 'b', 'c'], categories=['d', 'c', 'b', 'a']) + ) + other = Categorical(['b', 'c', 'a'], categories=['a', 'c', 'b', 'd']) + result = ser.where([True, False, True], other) + expected = pd.Series(Categorical(['a', 'c', 'c'], dtype=ser.dtype)) + tm.assert_series_equal(result, expected) + + def test_where_warns(self): + ser = pd.Series(Categorical(['a', 'b', 'c'])) + with tm.assert_produces_warning(FutureWarning): + result = ser.where([True, False, True], 'd') + + expected = pd.Series(np.array(['a', 'd', 'c'], dtype='object')) + tm.assert_series_equal(result, expected) + + def test_where_ordered_differs_rasies(self): + ser = pd.Series( + Categorical(['a', 'b', 'c'], categories=['d', 'c', 'b', 'a'], + ordered=True) + ) + other = Categorical(['b', 'c', 'a'], categories=['a', 'c', 'b', 'd'], + ordered=True) + with tm.assert_produces_warning(FutureWarning): + result = ser.where([True, False, True], other) + + expected = pd.Series(np.array(['a', 'c', 'c'], dtype=object)) + tm.assert_series_equal(result, expected) + @pytest.mark.parametrize("index", [True, False]) def test_mask_with_boolean(index): @@ -145,3 +239,30 @@ def test_mask_with_boolean_raises(index): with pytest.raises(ValueError, match='NA / NaN'): s[idx] + + +@pytest.fixture +def non_coercible_categorical(monkeypatch): + """ + Monkeypatch Categorical.__array__ to ensure no implicit conversion. + + Raises + ------ + ValueError + When Categorical.__array__ is called. + """ + # TODO(Categorical): identify other places where this may be + # useful and move to a conftest.py + def array(self, dtype=None): + raise ValueError("I cannot be converted.") + + with monkeypatch.context() as m: + m.setattr(Categorical, "__array__", array) + yield + + +def test_series_at(non_coercible_categorical): + arr = Categorical(['a', 'b', 'c']) + ser = Series(arr) + result = ser.at[0] + assert result == 'a' diff --git a/pandas/tests/arrays/interval/test_interval.py b/pandas/tests/arrays/interval/test_interval.py index a04579dbbb6b1..9604010571294 100644 --- a/pandas/tests/arrays/interval/test_interval.py +++ b/pandas/tests/arrays/interval/test_interval.py @@ -2,7 +2,8 @@ import numpy as np import pytest -from pandas import Index, IntervalIndex, date_range, timedelta_range +import pandas as pd +from pandas import Index, Interval, IntervalIndex, date_range, timedelta_range from pandas.core.arrays import IntervalArray import pandas.util.testing as tm @@ -50,6 +51,17 @@ def test_set_closed(self, closed, new_closed): expected = IntervalArray.from_breaks(range(10), closed=new_closed) tm.assert_extension_array_equal(result, expected) + @pytest.mark.parametrize('other', [ + Interval(0, 1, closed='right'), + IntervalArray.from_breaks([1, 2, 3, 4], closed='right'), + ]) + def test_where_raises(self, other): + ser = pd.Series(IntervalArray.from_breaks([1, 2, 3, 4], + closed='left')) + match = "'value.closed' is 'right', expected 'left'." + with pytest.raises(ValueError, match=match): + ser.where([True, False, True], other=other) + class TestSetitem(object): diff --git a/pandas/tests/arrays/sparse/test_array.py b/pandas/tests/arrays/sparse/test_array.py index b8cef92f6a6d4..7d8cc34ae1462 100644 --- a/pandas/tests/arrays/sparse/test_array.py +++ b/pandas/tests/arrays/sparse/test_array.py @@ -357,10 +357,10 @@ def setitem(): def setslice(): self.arr[1:5] = 2 - with pytest.raises(TypeError, match="item assignment"): + with pytest.raises(TypeError, match="assignment via setitem"): setitem() - with pytest.raises(TypeError, match="item assignment"): + with pytest.raises(TypeError, match="assignment via setitem"): setslice() def test_constructor_from_too_large_array(self): diff --git a/pandas/tests/arrays/test_period.py b/pandas/tests/arrays/test_period.py index bf139bb0ce616..4425cc8eb1139 100644 --- a/pandas/tests/arrays/test_period.py +++ b/pandas/tests/arrays/test_period.py @@ -197,6 +197,21 @@ def test_sub_period(): arr - other +# ---------------------------------------------------------------------------- +# Methods + +@pytest.mark.parametrize('other', [ + pd.Period('2000', freq='H'), + period_array(['2000', '2001', '2000'], freq='H') +]) +def test_where_different_freq_raises(other): + ser = pd.Series(period_array(['2000', '2001', '2002'], freq='D')) + cond = np.array([True, False, True]) + with pytest.raises(IncompatibleFrequency, + match="Input has different freq=H"): + ser.where(cond, other) + + # ---------------------------------------------------------------------------- # Printing diff --git a/pandas/tests/extension/base/methods.py b/pandas/tests/extension/base/methods.py index 677963078176d..4a409a84f3db4 100644 --- a/pandas/tests/extension/base/methods.py +++ b/pandas/tests/extension/base/methods.py @@ -164,7 +164,6 @@ def test_combine_add(self, data_repeated): orig_data1._from_sequence([a + val for a in list(orig_data1)])) self.assert_series_equal(result, expected) - @pytest.mark.xfail(reason="GH-24147", strict=True) def test_combine_first(self, data): # https://github.com/pandas-dev/pandas/issues/24147 a = pd.Series(data[:3]) @@ -231,3 +230,37 @@ def test_hash_pandas_object_works(self, data, as_frame): a = pd.util.hash_pandas_object(data) b = pd.util.hash_pandas_object(data) self.assert_equal(a, b) + + @pytest.mark.parametrize("as_frame", [True, False]) + def test_where_series(self, data, na_value, as_frame): + assert data[0] != data[1] + cls = type(data) + a, b = data[:2] + + ser = pd.Series(cls._from_sequence([a, a, b, b], dtype=data.dtype)) + cond = np.array([True, True, False, False]) + + if as_frame: + ser = ser.to_frame(name='a') + cond = cond.reshape(-1, 1) + + result = ser.where(cond) + expected = pd.Series(cls._from_sequence([a, a, na_value, na_value], + dtype=data.dtype)) + + if as_frame: + expected = expected.to_frame(name='a') + self.assert_equal(result, expected) + + # array other + cond = np.array([True, False, True, True]) + other = cls._from_sequence([a, b, a, b], dtype=data.dtype) + if as_frame: + other = pd.DataFrame({"a": other}) + cond = pd.DataFrame({"a": cond}) + result = ser.where(cond, other) + expected = pd.Series(cls._from_sequence([a, b, b, b], + dtype=data.dtype)) + if as_frame: + expected = expected.to_frame(name='a') + self.assert_equal(result, expected) diff --git a/pandas/tests/extension/conftest.py b/pandas/tests/extension/conftest.py index 7758bd01840ae..5349dd919f2a2 100644 --- a/pandas/tests/extension/conftest.py +++ b/pandas/tests/extension/conftest.py @@ -11,7 +11,11 @@ def dtype(): @pytest.fixture def data(): - """Length-100 array for this type.""" + """Length-100 array for this type. + + * data[0] and data[1] should both be non missing + * data[0] and data[1] should not gbe equal + """ raise NotImplementedError diff --git a/pandas/tests/extension/json/test_json.py b/pandas/tests/extension/json/test_json.py index a941b562fe1ec..a35997b07fd83 100644 --- a/pandas/tests/extension/json/test_json.py +++ b/pandas/tests/extension/json/test_json.py @@ -217,10 +217,21 @@ def test_combine_le(self, data_repeated): def test_combine_add(self, data_repeated): pass + @pytest.mark.skip(reason="combine for JSONArray not supported") + def test_combine_first(self, data): + pass + @unhashable def test_hash_pandas_object_works(self, data, kind): super().test_hash_pandas_object_works(data, kind) + @pytest.mark.skip(reason="broadcasting error") + def test_where_series(self, data, na_value): + # Fails with + # *** ValueError: operands could not be broadcast together + # with shapes (4,) (4,) (0,) + super().test_where_series(data, na_value) + class TestCasting(BaseJSON, base.BaseCastingTests): @pytest.mark.skip(reason="failing on np.array(self, dtype=str)") diff --git a/pandas/tests/extension/test_categorical.py b/pandas/tests/extension/test_categorical.py index 5b873b337880e..6106bc3d58620 100644 --- a/pandas/tests/extension/test_categorical.py +++ b/pandas/tests/extension/test_categorical.py @@ -25,7 +25,14 @@ def make_data(): - return np.random.choice(list(string.ascii_letters), size=100) + while True: + values = np.random.choice(list(string.ascii_letters), size=100) + # ensure we meet the requirements + # 1. first two not null + # 2. first and second are different + if values[0] != values[1]: + break + return values @pytest.fixture @@ -35,7 +42,11 @@ def dtype(): @pytest.fixture def data(): - """Length-100 PeriodArray for semantics test.""" + """Length-100 array for this type. + + * data[0] and data[1] should both be non missing + * data[0] and data[1] should not gbe equal + """ return Categorical(make_data()) diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index 891e5f4dd9a95..ea849a78cda12 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -13,6 +13,8 @@ def make_data(fill_value): data = np.random.uniform(size=100) else: data = np.random.randint(1, 100, size=100) + if data[0] == data[1]: + data[0] += 1 data[2::3] = fill_value return data @@ -255,6 +257,35 @@ def test_fillna_copy_series(self, data_missing): def test_fillna_length_mismatch(self, data_missing): pass + def test_where_series(self, data, na_value): + assert data[0] != data[1] + cls = type(data) + a, b = data[:2] + + ser = pd.Series(cls._from_sequence([a, a, b, b], dtype=data.dtype)) + + cond = np.array([True, True, False, False]) + result = ser.where(cond) + + new_dtype = SparseDtype('float', 0.0) + expected = pd.Series(cls._from_sequence([a, a, na_value, na_value], + dtype=new_dtype)) + self.assert_series_equal(result, expected) + + other = cls._from_sequence([a, b, a, b], dtype=data.dtype) + cond = np.array([True, False, True, True]) + result = ser.where(cond, other) + expected = pd.Series(cls._from_sequence([a, b, b, b], + dtype=data.dtype)) + self.assert_series_equal(result, expected) + + def test_combine_first(self, data): + if data.dtype.subtype == 'int': + # Right now this is upcasted to float, just like combine_first + # for Series[int] + pytest.skip("TODO(SparseArray.__setitem__ will preserve dtype.") + super(TestMethods, self).test_combine_first(data) + class TestCasting(BaseSparseTests, base.BaseCastingTests): pass diff --git a/pandas/tests/frame/test_analytics.py b/pandas/tests/frame/test_analytics.py index 6c30f3fb02fb0..88262220015c7 100644 --- a/pandas/tests/frame/test_analytics.py +++ b/pandas/tests/frame/test_analytics.py @@ -1841,10 +1841,12 @@ def test_clip(self, float_frame): median = float_frame.median().median() original = float_frame.copy() - capped = float_frame.clip_upper(median) + with tm.assert_produces_warning(FutureWarning): + capped = float_frame.clip_upper(median) assert not (capped.values > median).any() - floored = float_frame.clip_lower(median) + with tm.assert_produces_warning(FutureWarning): + floored = float_frame.clip_lower(median) assert not (floored.values < median).any() double = float_frame.clip(upper=median, lower=median) @@ -1858,11 +1860,13 @@ def test_inplace_clip(self, float_frame): median = float_frame.median().median() frame_copy = float_frame.copy() - frame_copy.clip_upper(median, inplace=True) + with tm.assert_produces_warning(FutureWarning): + frame_copy.clip_upper(median, inplace=True) assert not (frame_copy.values > median).any() frame_copy = float_frame.copy() - frame_copy.clip_lower(median, inplace=True) + with tm.assert_produces_warning(FutureWarning): + frame_copy.clip_lower(median, inplace=True) assert not (frame_copy.values < median).any() frame_copy = float_frame.copy() @@ -2263,7 +2267,8 @@ def test_series_broadcasting(self): s_nan = Series([np.nan, np.nan, 1]) with tm.assert_produces_warning(None): - df_nan.clip_lower(s, axis=0) + with tm.assert_produces_warning(FutureWarning): + df_nan.clip_lower(s, axis=0) for op in ['lt', 'le', 'gt', 'ge', 'eq', 'ne']: getattr(df, op)(s_nan, axis=0) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index 54a04ab6f80fd..11cefec4f34cf 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -769,3 +769,14 @@ def test_all_custom_freq(self, freq): msg = 'invalid custom frequency string: {freq}' with pytest.raises(ValueError, match=msg.format(freq=bad_freq)): bdate_range(START, END, freq=bad_freq) + + @pytest.mark.parametrize('start_end', [ + ('2018-01-01T00:00:01.000Z', '2018-01-03T00:00:01.000Z'), + ('2018-01-01T00:00:00.010Z', '2018-01-03T00:00:00.010Z'), + ('2001-01-01T00:00:00.010Z', '2001-01-03T00:00:00.010Z')]) + def test_range_with_millisecond_resolution(self, start_end): + # https://github.com/pandas-dev/pandas/issues/24110 + start, end = start_end + result = pd.date_range(start=start, end=end, periods=2, closed='left') + expected = DatetimeIndex([start]) + tm.assert_index_equal(result, expected) diff --git a/pandas/tests/indexing/multiindex/test_getitem.py b/pandas/tests/indexing/multiindex/test_getitem.py index 00b30bab37441..1013bb3e90149 100644 --- a/pandas/tests/indexing/multiindex/test_getitem.py +++ b/pandas/tests/indexing/multiindex/test_getitem.py @@ -1,5 +1,3 @@ -from warnings import catch_warnings, simplefilter - import numpy as np import pytest @@ -11,335 +9,339 @@ from pandas.util import testing as tm -@pytest.mark.filterwarnings("ignore:\\n.ix:DeprecationWarning") -class TestMultiIndexGetItem(object): - - def test_series_getitem_multiindex(self): - - # GH 6018 - # series regression getitem with a multi-index - - s = Series([1, 2, 3]) - s.index = MultiIndex.from_tuples([(0, 0), (1, 1), (2, 1)]) - - result = s[:, 0] - expected = Series([1], index=[0]) - tm.assert_series_equal(result, expected) - - result = s.loc[:, 1] - expected = Series([2, 3], index=[1, 2]) - tm.assert_series_equal(result, expected) - - # xs - result = s.xs(0, level=0) - expected = Series([1], index=[0]) - tm.assert_series_equal(result, expected) - - result = s.xs(1, level=1) - expected = Series([2, 3], index=[1, 2]) - tm.assert_series_equal(result, expected) - - # GH6258 - dt = list(date_range('20130903', periods=3)) - idx = MultiIndex.from_product([list('AB'), dt]) - s = Series([1, 3, 4, 1, 3, 4], index=idx) +@pytest.mark.parametrize('access_method', [lambda s, x: s[:, x], + lambda s, x: s.loc[:, x], + lambda s, x: s.xs(x, level=1)]) +@pytest.mark.parametrize('level1_value, expected', [ + (0, Series([1], index=[0])), + (1, Series([2, 3], index=[1, 2])) +]) +def test_series_getitem_multiindex(access_method, level1_value, expected): + + # GH 6018 + # series regression getitem with a multi-index + + s = Series([1, 2, 3]) + s.index = MultiIndex.from_tuples([(0, 0), (1, 1), (2, 1)]) + result = access_method(s, level1_value) + tm.assert_series_equal(result, expected) + + +def test_series_getitem_multiindex_xs(): + # GH6258 + dt = list(date_range('20130903', periods=3)) + idx = MultiIndex.from_product([list('AB'), dt]) + s = Series([1, 3, 4, 1, 3, 4], index=idx) + + result = s.xs('20130903', level=1) + expected = Series([1, 1], index=list('AB')) + tm.assert_series_equal(result, expected) + + +def test_series_getitem_multiindex_xs_by_label(): + # GH5684 + idx = MultiIndex.from_tuples([('a', 'one'), ('a', 'two'), ('b', 'one'), + ('b', 'two')]) + s = Series([1, 2, 3, 4], index=idx) + s.index.set_names(['L1', 'L2'], inplace=True) + result = s.xs('one', level='L2') + expected = Series([1, 3], index=['a', 'b']) + expected.index.set_names(['L1'], inplace=True) + tm.assert_series_equal(result, expected) + + +@pytest.mark.parametrize('level0_value', ['D', 'A']) +def test_getitem_duplicates_multiindex(level0_value): + # GH 5725 the 'A' happens to be a valid Timestamp so the doesn't raise + # the appropriate error, only in PY3 of course! + + index = MultiIndex(levels=[[level0_value, 'B', 'C'], + [0, 26, 27, 37, 57, 67, 75, 82]], + codes=[[0, 0, 0, 1, 2, 2, 2, 2, 2, 2], + [1, 3, 4, 6, 0, 2, 2, 3, 5, 7]], + names=['tag', 'day']) + arr = np.random.randn(len(index), 1) + df = DataFrame(arr, index=index, columns=['val']) + + # confirm indexing on missing value raises KeyError + if level0_value != 'A': + msg = "'A'" + with pytest.raises(KeyError, match=msg): + df.val['A'] - result = s.xs('20130903', level=1) - expected = Series([1, 1], index=list('AB')) - tm.assert_series_equal(result, expected) + msg = "'X'" + with pytest.raises(KeyError, match=msg): + df.val['X'] + + result = df.val[level0_value] + expected = Series(arr.ravel()[0:3], name='val', index=Index( + [26, 37, 57], name='day')) + tm.assert_series_equal(result, expected) + + +@pytest.mark.parametrize('indexer, is_level1, expected_error', [ + ([], False, None), # empty ok + (['A'], False, None), + (['A', 'D'], False, None), + (['D'], False, r"\['D'\] not in index"), # not any values found + (pd.IndexSlice[:, ['foo']], True, None), + (pd.IndexSlice[:, ['foo', 'bah']], True, None) +]) +def test_getitem_duplicates_multiindex_missing_indexers(indexer, is_level1, + expected_error): + # GH 7866 + # multi-index slicing with missing indexers + idx = MultiIndex.from_product([['A', 'B', 'C'], + ['foo', 'bar', 'baz']], + names=['one', 'two']) + s = Series(np.arange(9, dtype='int64'), index=idx).sort_index() + + if indexer == []: + expected = s.iloc[[]] + elif is_level1: + expected = Series([0, 3, 6], index=MultiIndex.from_product( + [['A', 'B', 'C'], ['foo']], names=['one', 'two'])).sort_index() + else: + exp_idx = MultiIndex.from_product([['A'], ['foo', 'bar', 'baz']], + names=['one', 'two']) + expected = Series(np.arange(3, dtype='int64'), + index=exp_idx).sort_index() - # GH5684 - idx = MultiIndex.from_tuples([('a', 'one'), ('a', 'two'), ('b', 'one'), - ('b', 'two')]) - s = Series([1, 2, 3, 4], index=idx) - s.index.set_names(['L1', 'L2'], inplace=True) - result = s.xs('one', level='L2') - expected = Series([1, 3], index=['a', 'b']) - expected.index.set_names(['L1'], inplace=True) + if expected_error is not None: + with pytest.raises(KeyError, match=expected_error): + s.loc[indexer] + else: + result = s.loc[indexer] tm.assert_series_equal(result, expected) - def test_getitem_duplicates_multiindex(self): - # GH 5725 the 'A' happens to be a valid Timestamp so the doesn't raise - # the appropriate error, only in PY3 of course! - - index = MultiIndex(levels=[['D', 'B', 'C'], - [0, 26, 27, 37, 57, 67, 75, 82]], - codes=[[0, 0, 0, 1, 2, 2, 2, 2, 2, 2], - [1, 3, 4, 6, 0, 2, 2, 3, 5, 7]], - names=['tag', 'day']) - arr = np.random.randn(len(index), 1) - df = DataFrame(arr, index=index, columns=['val']) - result = df.val['D'] - expected = Series(arr.ravel()[0:3], name='val', index=Index( - [26, 37, 57], name='day')) - tm.assert_series_equal(result, expected) - def f(): - df.val['A'] +@pytest.mark.parametrize('columns_indexer', [ + ([], slice(None)), + (['foo'], []) +]) +def test_getitem_duplicates_multiindex_empty_indexer(columns_indexer): + # GH 8737 + # empty indexer + multi_index = MultiIndex.from_product((['foo', 'bar', 'baz'], + ['alpha', 'beta'])) + df = DataFrame(np.random.randn(5, 6), index=range(5), columns=multi_index) + df = df.sort_index(level=0, axis=1) + + expected = DataFrame(index=range(5), columns=multi_index.reindex([])[0]) + result = df.loc[:, columns_indexer] + tm.assert_frame_equal(result, expected) + + +def test_getitem_duplicates_multiindex_non_scalar_type_object(): + # regression from < 0.14.0 + # GH 7914 + df = DataFrame([[np.mean, np.median], ['mean', 'median']], + columns=MultiIndex.from_tuples([('functs', 'mean'), + ('functs', 'median')]), + index=['function', 'name']) + result = df.loc['function', ('functs', 'mean')] + expected = np.mean + assert result == expected + + +def test_getitem_simple(multiindex_dataframe_random_data): + frame = multiindex_dataframe_random_data + df = frame.T + + col = df['foo', 'one'] + tm.assert_almost_equal(col.values, df.values[:, 0]) + msg = r"\('foo', 'four'\)" + with pytest.raises(KeyError, match=msg): + df[('foo', 'four')] + msg = "'foobar'" + with pytest.raises(KeyError, match=msg): + df['foobar'] - pytest.raises(KeyError, f) - def f(): - df.val['X'] - - pytest.raises(KeyError, f) +@pytest.mark.filterwarnings("ignore:\\n.ix:DeprecationWarning") +def test_series_getitem(multiindex_year_month_day_dataframe_random_data): + ymd = multiindex_year_month_day_dataframe_random_data + s = ymd['A'] - # A is treated as a special Timestamp - index = MultiIndex(levels=[['A', 'B', 'C'], - [0, 26, 27, 37, 57, 67, 75, 82]], - codes=[[0, 0, 0, 1, 2, 2, 2, 2, 2, 2], - [1, 3, 4, 6, 0, 2, 2, 3, 5, 7]], - names=['tag', 'day']) - df = DataFrame(arr, index=index, columns=['val']) - result = df.val['A'] - expected = Series(arr.ravel()[0:3], name='val', index=Index( - [26, 37, 57], name='day')) - tm.assert_series_equal(result, expected) + result = s[2000, 3] - def f(): - df.val['X'] + # TODO(wesm): unused? + # result2 = s.loc[2000, 3] - pytest.raises(KeyError, f) + expected = s.reindex(s.index[42:65]) + expected.index = expected.index.droplevel(0).droplevel(0) + tm.assert_series_equal(result, expected) - # GH 7866 - # multi-index slicing with missing indexers - idx = MultiIndex.from_product([['A', 'B', 'C'], - ['foo', 'bar', 'baz']], - names=['one', 'two']) - s = Series(np.arange(9, dtype='int64'), index=idx).sort_index() + result = s[2000, 3, 10] + expected = s[49] + assert result == expected - exp_idx = MultiIndex.from_product([['A'], ['foo', 'bar', 'baz']], - names=['one', 'two']) - expected = Series(np.arange(3, dtype='int64'), - index=exp_idx).sort_index() + # fancy + expected = s.reindex(s.index[49:51]) + result = s.loc[[(2000, 3, 10), (2000, 3, 13)]] + tm.assert_series_equal(result, expected) - result = s.loc[['A']] - tm.assert_series_equal(result, expected) - result = s.loc[['A', 'D']] - tm.assert_series_equal(result, expected) + result = s.ix[[(2000, 3, 10), (2000, 3, 13)]] + tm.assert_series_equal(result, expected) - # not any values found - pytest.raises(KeyError, lambda: s.loc[['D']]) + # key error + msg = "356" + with pytest.raises(KeyError, match=msg): + s.__getitem__((2000, 3, 4)) - # empty ok - result = s.loc[[]] - expected = s.iloc[[]] - tm.assert_series_equal(result, expected) - idx = pd.IndexSlice - expected = Series([0, 3, 6], index=MultiIndex.from_product( - [['A', 'B', 'C'], ['foo']], names=['one', 'two'])).sort_index() +def test_series_getitem_corner( + multiindex_year_month_day_dataframe_random_data): + ymd = multiindex_year_month_day_dataframe_random_data + s = ymd['A'] - result = s.loc[idx[:, ['foo']]] - tm.assert_series_equal(result, expected) - result = s.loc[idx[:, ['foo', 'bah']]] - tm.assert_series_equal(result, expected) + # don't segfault, GH #495 + # out of bounds access + msg = "index out of bounds" + with pytest.raises(IndexError, match=msg): + s.__getitem__(len(ymd)) - # GH 8737 - # empty indexer - multi_index = MultiIndex.from_product((['foo', 'bar', 'baz'], - ['alpha', 'beta'])) - df = DataFrame( - np.random.randn(5, 6), index=range(5), columns=multi_index) - df = df.sort_index(level=0, axis=1) - - expected = DataFrame(index=range(5), - columns=multi_index.reindex([])[0]) - result1 = df.loc[:, ([], slice(None))] - result2 = df.loc[:, (['foo'], [])] - tm.assert_frame_equal(result1, expected) - tm.assert_frame_equal(result2, expected) - - # regression from < 0.14.0 - # GH 7914 - df = DataFrame([[np.mean, np.median], ['mean', 'median']], - columns=MultiIndex.from_tuples([('functs', 'mean'), - ('functs', 'median')]), - index=['function', 'name']) - result = df.loc['function', ('functs', 'mean')] - assert result == np.mean - - def test_getitem_simple(self, multiindex_dataframe_random_data): - frame = multiindex_dataframe_random_data - df = frame.T - - col = df['foo', 'one'] - tm.assert_almost_equal(col.values, df.values[:, 0]) - with pytest.raises(KeyError): - df[('foo', 'four')] - with pytest.raises(KeyError): - df['foobar'] - - def test_series_getitem( - self, multiindex_year_month_day_dataframe_random_data): - ymd = multiindex_year_month_day_dataframe_random_data - s = ymd['A'] - - result = s[2000, 3] - - # TODO(wesm): unused? - # result2 = s.loc[2000, 3] - - expected = s.reindex(s.index[42:65]) - expected.index = expected.index.droplevel(0).droplevel(0) - tm.assert_series_equal(result, expected) + # generator + result = s[(x > 0 for x in s)] + expected = s[s > 0] + tm.assert_series_equal(result, expected) - result = s[2000, 3, 10] - expected = s[49] - assert result == expected - # fancy - expected = s.reindex(s.index[49:51]) - result = s.loc[[(2000, 3, 10), (2000, 3, 13)]] - tm.assert_series_equal(result, expected) +def test_frame_getitem_multicolumn_empty_level(): + f = DataFrame({'a': ['1', '2', '3'], 'b': ['2', '3', '4']}) + f.columns = [['level1 item1', 'level1 item2'], ['', 'level2 item2'], + ['level3 item1', 'level3 item2']] - with catch_warnings(record=True): - simplefilter("ignore", DeprecationWarning) - result = s.ix[[(2000, 3, 10), (2000, 3, 13)]] - tm.assert_series_equal(result, expected) + result = f['level1 item1'] + expected = DataFrame([['1'], ['2'], ['3']], index=f.index, + columns=['level3 item1']) + tm.assert_frame_equal(result, expected) - # key error - pytest.raises(KeyError, s.__getitem__, (2000, 3, 4)) - def test_series_getitem_corner( - self, multiindex_year_month_day_dataframe_random_data): - ymd = multiindex_year_month_day_dataframe_random_data - s = ymd['A'] +@pytest.mark.filterwarnings("ignore:\\n.ix:DeprecationWarning") +def test_getitem_tuple_plus_slice(): + # GH #671 + df = DataFrame({'a': lrange(10), + 'b': lrange(10), + 'c': np.random.randn(10), + 'd': np.random.randn(10)}) - # don't segfault, GH #495 - # out of bounds access - pytest.raises(IndexError, s.__getitem__, len(ymd)) + idf = df.set_index(['a', 'b']) - # generator - result = s[(x > 0 for x in s)] - expected = s[s > 0] - tm.assert_series_equal(result, expected) + result = idf.loc[(0, 0), :] + expected = idf.loc[0, 0] + expected2 = idf.xs((0, 0)) + expected3 = idf.ix[0, 0] - def test_frame_getitem_multicolumn_empty_level(self): - f = DataFrame({'a': ['1', '2', '3'], 'b': ['2', '3', '4']}) - f.columns = [['level1 item1', 'level1 item2'], ['', 'level2 item2'], - ['level3 item1', 'level3 item2']] + tm.assert_series_equal(result, expected) + tm.assert_series_equal(result, expected2) + tm.assert_series_equal(result, expected3) - result = f['level1 item1'] - expected = DataFrame([['1'], ['2'], ['3']], index=f.index, - columns=['level3 item1']) - tm.assert_frame_equal(result, expected) - def test_getitem_tuple_plus_slice(self): - # GH #671 - df = DataFrame({'a': lrange(10), - 'b': lrange(10), - 'c': np.random.randn(10), - 'd': np.random.randn(10)}) +def test_getitem_toplevel(multiindex_dataframe_random_data): + frame = multiindex_dataframe_random_data + df = frame.T - idf = df.set_index(['a', 'b']) + result = df['foo'] + expected = df.reindex(columns=df.columns[:3]) + expected.columns = expected.columns.droplevel(0) + tm.assert_frame_equal(result, expected) - result = idf.loc[(0, 0), :] - expected = idf.loc[0, 0] - expected2 = idf.xs((0, 0)) - with catch_warnings(record=True): - simplefilter("ignore", DeprecationWarning) - expected3 = idf.ix[0, 0] + result = df['bar'] + result2 = df.loc[:, 'bar'] - tm.assert_series_equal(result, expected) - tm.assert_series_equal(result, expected2) - tm.assert_series_equal(result, expected3) + expected = df.reindex(columns=df.columns[3:5]) + expected.columns = expected.columns.droplevel(0) + tm.assert_frame_equal(result, expected) + tm.assert_frame_equal(result, result2) - def test_getitem_toplevel(self, multiindex_dataframe_random_data): - frame = multiindex_dataframe_random_data - df = frame.T - result = df['foo'] - expected = df.reindex(columns=df.columns[:3]) - expected.columns = expected.columns.droplevel(0) - tm.assert_frame_equal(result, expected) +def test_getitem_int(multiindex_dataframe_random_data): + levels = [[0, 1], [0, 1, 2]] + codes = [[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]] + index = MultiIndex(levels=levels, codes=codes) - result = df['bar'] - result2 = df.loc[:, 'bar'] + frame = DataFrame(np.random.randn(6, 2), index=index) - expected = df.reindex(columns=df.columns[3:5]) - expected.columns = expected.columns.droplevel(0) - tm.assert_frame_equal(result, expected) - tm.assert_frame_equal(result, result2) + result = frame.loc[1] + expected = frame[-3:] + expected.index = expected.index.droplevel(0) + tm.assert_frame_equal(result, expected) - def test_getitem_int(self, multiindex_dataframe_random_data): - levels = [[0, 1], [0, 1, 2]] - codes = [[0, 0, 0, 1, 1, 1], [0, 1, 2, 0, 1, 2]] - index = MultiIndex(levels=levels, codes=codes) + # raises exception + msg = "3" + with pytest.raises(KeyError, match=msg): + frame.loc.__getitem__(3) - frame = DataFrame(np.random.randn(6, 2), index=index) + # however this will work + frame = multiindex_dataframe_random_data + result = frame.iloc[2] + expected = frame.xs(frame.index[2]) + tm.assert_series_equal(result, expected) - result = frame.loc[1] - expected = frame[-3:] - expected.index = expected.index.droplevel(0) - tm.assert_frame_equal(result, expected) - # raises exception - pytest.raises(KeyError, frame.loc.__getitem__, 3) +def test_frame_getitem_view(multiindex_dataframe_random_data): + frame = multiindex_dataframe_random_data + df = frame.T.copy() - # however this will work - frame = multiindex_dataframe_random_data - result = frame.iloc[2] - expected = frame.xs(frame.index[2]) - tm.assert_series_equal(result, expected) + # this works because we are modifying the underlying array + # really a no-no + df['foo'].values[:] = 0 + assert (df['foo'].values == 0).all() - def test_frame_getitem_view(self, multiindex_dataframe_random_data): - frame = multiindex_dataframe_random_data - df = frame.T.copy() + # but not if it's mixed-type + df['foo', 'four'] = 'foo' + df = df.sort_index(level=0, axis=1) - # this works because we are modifying the underlying array - # really a no-no - df['foo'].values[:] = 0 - assert (df['foo'].values == 0).all() + # this will work, but will raise/warn as its chained assignment + def f(): + df['foo']['one'] = 2 + return df - # but not if it's mixed-type - df['foo', 'four'] = 'foo' - df = df.sort_index(level=0, axis=1) + msg = "A value is trying to be set on a copy of a slice from a DataFrame" + with pytest.raises(com.SettingWithCopyError, match=msg): + df['foo']['one'] = 2 - # this will work, but will raise/warn as its chained assignment - def f(): - df['foo']['one'] = 2 - return df + try: + df = f() + except ValueError: + pass + assert (df['foo', 'one'] == 0).all() - pytest.raises(com.SettingWithCopyError, f) - try: - df = f() - except ValueError: - pass - assert (df['foo', 'one'] == 0).all() +def test_getitem_lowerdim_corner(multiindex_dataframe_random_data): + frame = multiindex_dataframe_random_data + msg = "11" + with pytest.raises(KeyError, match=msg): + frame.loc.__getitem__((('bar', 'three'), 'B')) - def test_getitem_lowerdim_corner(self, multiindex_dataframe_random_data): - frame = multiindex_dataframe_random_data - pytest.raises(KeyError, frame.loc.__getitem__, - (('bar', 'three'), 'B')) + # in theory should be inserting in a sorted space???? + frame.loc[('bar', 'three'), 'B'] = 0 + assert frame.sort_index().loc[('bar', 'three'), 'B'] == 0 - # in theory should be inserting in a sorted space???? - frame.loc[('bar', 'three'), 'B'] = 0 - assert frame.sort_index().loc[('bar', 'three'), 'B'] == 0 - @pytest.mark.parametrize('unicode_strings', [True, False]) - def test_mixed_depth_get(self, unicode_strings): - # If unicode_strings is True, the column labels in dataframe - # construction will use unicode strings in Python 2 (pull request - # #17099). +@pytest.mark.parametrize('unicode_strings', [True, False]) +def test_mixed_depth_get(unicode_strings): + # If unicode_strings is True, the column labels in dataframe + # construction will use unicode strings in Python 2 (pull request + # #17099). - arrays = [['a', 'top', 'top', 'routine1', 'routine1', 'routine2'], - ['', 'OD', 'OD', 'result1', 'result2', 'result1'], - ['', 'wx', 'wy', '', '', '']] + arrays = [['a', 'top', 'top', 'routine1', 'routine1', 'routine2'], + ['', 'OD', 'OD', 'result1', 'result2', 'result1'], + ['', 'wx', 'wy', '', '', '']] - if unicode_strings: - arrays = [[u(s) for s in arr] for arr in arrays] + if unicode_strings: + arrays = [[u(s) for s in arr] for arr in arrays] - tuples = sorted(zip(*arrays)) - index = MultiIndex.from_tuples(tuples) - df = DataFrame(np.random.randn(4, 6), columns=index) + tuples = sorted(zip(*arrays)) + index = MultiIndex.from_tuples(tuples) + df = DataFrame(np.random.randn(4, 6), columns=index) - result = df['a'] - expected = df['a', '', ''].rename('a') - tm.assert_series_equal(result, expected) + result = df['a'] + expected = df['a', '', ''].rename('a') + tm.assert_series_equal(result, expected) - result = df['routine1', 'result1'] - expected = df['routine1', 'result1', ''] - expected = expected.rename(('routine1', 'result1')) - tm.assert_series_equal(result, expected) + result = df['routine1', 'result1'] + expected = df['routine1', 'result1', ''] + expected = expected.rename(('routine1', 'result1')) + tm.assert_series_equal(result, expected) diff --git a/pandas/tests/series/test_analytics.py b/pandas/tests/series/test_analytics.py index a9c8e855cd324..81d60aba44b0f 100644 --- a/pandas/tests/series/test_analytics.py +++ b/pandas/tests/series/test_analytics.py @@ -924,8 +924,10 @@ def test_matmul(self): def test_clip(self, datetime_series): val = datetime_series.median() - assert datetime_series.clip_lower(val).min() == val - assert datetime_series.clip_upper(val).max() == val + with tm.assert_produces_warning(FutureWarning): + assert datetime_series.clip_lower(val).min() == val + with tm.assert_produces_warning(FutureWarning): + assert datetime_series.clip_upper(val).max() == val assert datetime_series.clip(lower=val).min() == val assert datetime_series.clip(upper=val).max() == val @@ -943,8 +945,10 @@ def test_clip_types_and_nulls(self): for s in sers: thresh = s[2] - lower = s.clip_lower(thresh) - upper = s.clip_upper(thresh) + with tm.assert_produces_warning(FutureWarning): + lower = s.clip_lower(thresh) + with tm.assert_produces_warning(FutureWarning): + upper = s.clip_upper(thresh) assert lower[notna(lower)].min() == thresh assert upper[notna(upper)].max() == thresh assert list(isna(s)) == list(isna(lower)) @@ -971,8 +975,12 @@ def test_clip_against_series(self): s = Series([1.0, 1.0, 4.0]) threshold = Series([1.0, 2.0, 3.0]) - assert_series_equal(s.clip_lower(threshold), Series([1.0, 2.0, 4.0])) - assert_series_equal(s.clip_upper(threshold), Series([1.0, 1.0, 3.0])) + with tm.assert_produces_warning(FutureWarning): + assert_series_equal(s.clip_lower(threshold), + Series([1.0, 2.0, 4.0])) + with tm.assert_produces_warning(FutureWarning): + assert_series_equal(s.clip_upper(threshold), + Series([1.0, 1.0, 3.0])) lower = Series([1.0, 2.0, 3.0]) upper = Series([1.5, 2.5, 3.5]) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 0f553cc4f2fe8..ecb02071c5bb6 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -174,6 +174,7 @@ def get_api_items(api_doc_fd): The name of the subsection in the API page where the object item is located. """ + current_module = 'pandas' previous_line = current_section = current_subsection = '' position = None for line in api_doc_fd: diff --git a/setup.cfg b/setup.cfg index bfffe56e088eb..30b4d13bd0a66 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,10 +32,18 @@ exclude = [flake8-rst] bootstrap = - import pandas as pd import numpy as np + import pandas as pd + np # avoiding error when importing again numpy or pandas + pd # (in some cases we want to do it to show users) ignore = E402, # module level import not at top of file W503, # line break before binary operator + # Classes/functions in different blocks can generate those errors + E302, # expected 2 blank lines, found 0 + E305, # expected 2 blank lines after class or function definition, found 0 + # We use semicolon at the end to avoid displaying plot objects + E703, # statement ends with a semicolon + exclude = doc/source/whatsnew/v0.7.0.rst doc/source/whatsnew/v0.7.3.rst @@ -63,31 +71,16 @@ exclude = doc/source/whatsnew/v0.19.0.rst doc/source/whatsnew/v0.20.0.rst doc/source/whatsnew/v0.21.0.rst - doc/source/whatsnew/v0.22.0.rst - doc/source/whatsnew/v0.23.0.rst doc/source/whatsnew/v0.23.1.rst doc/source/whatsnew/v0.23.2.rst - doc/source/whatsnew/v0.24.0.rst - doc/source/10min.rst - doc/source/advanced.rst doc/source/basics.rst - doc/source/categorical.rst doc/source/contributing_docstring.rst - doc/source/contributing.rst - doc/source/dsintro.rst doc/source/enhancingperf.rst - doc/source/extending.rst doc/source/groupby.rst doc/source/indexing.rst - doc/source/merging.rst doc/source/missing_data.rst doc/source/options.rst doc/source/release.rst - doc/source/comparison_with_sas.rst - doc/source/comparison_with_sql.rst - doc/source/comparison_with_stata.rst - doc/source/reshaping.rst - doc/source/visualization.rst [yapf] diff --git a/tmp.xlsx b/tmp.xlsx deleted file mode 100644 index 199e9049bfa9667b3a19a8f7a2d8f0f66834f2e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5417 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