Skip to content

Commit e7cc2ac

Browse files
committed
Merge remote-tracking branch 'upstream/master' into ea-repr
2 parents 740f9e5 + 30c1290 commit e7cc2ac

25 files changed

+3676
-3137
lines changed

doc/source/api.rst

+1
Original file line numberDiff line numberDiff line change
@@ -2482,6 +2482,7 @@ Style Application
24822482
Styler.set_properties
24832483
Styler.set_uuid
24842484
Styler.clear
2485+
Styler.pipe
24852486

24862487
Builtin Styles
24872488
~~~~~~~~~~~~~~

doc/source/whatsnew/v0.24.0.rst

+28-1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,30 @@ array, but rather an ``ExtensionArray``:
184184
This is the same behavior as ``Series.values`` for categorical data. See
185185
:ref:`whatsnew_0240.api_breaking.interval_values` for more.
186186

187+
188+
.. _whatsnew_0240.enhancements.styler_pipe:
189+
190+
New ``Styler.pipe()`` method
191+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
192+
The :class:`~pandas.io.formats.style.Styler` class has gained a
193+
:meth:`~pandas.io.formats.style.Styler.pipe` method (:issue:`23229`). This provides a
194+
convenient way to apply users' predefined styling functions, and can help reduce
195+
"boilerplate" when using DataFrame styling functionality repeatedly within a notebook.
196+
197+
.. ipython:: python
198+
199+
df = pandas.DataFrame({'N': [1250, 1500, 1750], 'X': [0.25, 0.35, 0.50]})
200+
201+
def format_and_align(styler):
202+
return (styler.format({'N': '{:,}', 'X': '{:.1%}'})
203+
.set_properties(**{'text-align': 'right'}))
204+
205+
df.style.pipe(format_and_align).set_caption('Summary of results.')
206+
207+
Similar methods already exist for other classes in pandas, including :meth:`DataFrame.pipe`,
208+
:meth:`Groupby.pipe`, and :meth:`Resampler.pipe`.
209+
210+
187211
.. _whatsnew_0240.enhancements.join_with_two_multiindexes:
188212

189213
Joining with two multi-indexes
@@ -225,6 +249,7 @@ For earlier versions this can be done using the following.
225249
pd.merge(left.reset_index(), right.reset_index(),
226250
on=['key'], how='inner').set_index(['key', 'X', 'Y'])
227251
252+
228253
.. _whatsnew_0240.enhancements.rename_axis:
229254

230255
Renaming names in a MultiIndex
@@ -248,6 +273,7 @@ Example:
248273
249274
See the :ref:`advanced docs on renaming<advanced.index_names>` for more details.
250275

276+
251277
.. _whatsnew_0240.enhancements.other:
252278

253279
Other Enhancements
@@ -1405,7 +1431,8 @@ Notice how we now instead output ``np.nan`` itself instead of a stringified form
14051431
- Bug in :meth:`read_csv()` in which unnecessary warnings were being raised when the dialect's values conflicted with the default arguments (:issue:`23761`)
14061432
- Bug in :meth:`read_html()` in which the error message was not displaying the valid flavors when an invalid one was provided (:issue:`23549`)
14071433
- Bug in :meth:`read_excel()` in which extraneous header names were extracted, even though none were specified (:issue:`11733`)
1408-
- Bug in :meth:`read_excel()` in which ``index_col=None`` was not being respected and parsing index columns anyway (:issue:`20480`)
1434+
- Bug in :meth:`read_excel()` in which column names were not being properly converted to string sometimes in Python 2.x (:issue:`23874`)
1435+
- Bug in :meth:`read_excel()` in which ``index_col=None`` was not being respected and parsing index columns anyway (:issue:`18792`, :issue:`20480`)
14091436
- Bug in :meth:`read_excel()` in which ``usecols`` was not being validated for proper column names when passed in as a string (:issue:`20480`)
14101437
- :func:`DataFrame.to_string()`, :func:`DataFrame.to_html()`, :func:`DataFrame.to_latex()` will correctly format output when a string is passed as the ``float_format`` argument (:issue:`21625`, :issue:`22270`)
14111438

pandas/_libs/tslib.pyx

+15-10
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ cdef inline object create_time_from_ts(
7676

7777
@cython.wraparound(False)
7878
@cython.boundscheck(False)
79-
def ints_to_pydatetime(int64_t[:] arr, tz=None, freq=None, box="datetime"):
79+
def ints_to_pydatetime(int64_t[:] arr, object tz=None, object freq=None,
80+
str box="datetime"):
8081
"""
8182
Convert an i8 repr to an ndarray of datetimes, date, time or Timestamp
8283
@@ -104,8 +105,9 @@ def ints_to_pydatetime(int64_t[:] arr, tz=None, freq=None, box="datetime"):
104105
int64_t[:] deltas
105106
Py_ssize_t pos
106107
npy_datetimestruct dts
107-
object dt
108-
int64_t value, delta
108+
object dt, new_tz
109+
str typ
110+
int64_t value, delta, local_value
109111
ndarray[object] result = np.empty(n, dtype=object)
110112
object (*func_create)(int64_t, npy_datetimestruct, object, object)
111113

@@ -303,7 +305,8 @@ def format_array_from_datetime(ndarray[int64_t] values, object tz=None,
303305
return result
304306

305307

306-
def array_with_unit_to_datetime(ndarray values, unit, errors='coerce'):
308+
def array_with_unit_to_datetime(ndarray values, object unit,
309+
str errors='coerce'):
307310
"""
308311
convert the ndarray according to the unit
309312
if errors:
@@ -458,10 +461,10 @@ def array_with_unit_to_datetime(ndarray values, unit, errors='coerce'):
458461

459462
@cython.wraparound(False)
460463
@cython.boundscheck(False)
461-
cpdef array_to_datetime(ndarray[object] values, errors='raise',
462-
dayfirst=False, yearfirst=False,
463-
format=None, utc=None,
464-
require_iso8601=False):
464+
cpdef array_to_datetime(ndarray[object] values, str errors='raise',
465+
bint dayfirst=False, bint yearfirst=False,
466+
object format=None, object utc=None,
467+
bint require_iso8601=False):
465468
"""
466469
Converts a 1D array of date-like values to a numpy array of either:
467470
1) datetime64[ns] data
@@ -510,9 +513,11 @@ cpdef array_to_datetime(ndarray[object] values, errors='raise',
510513
bint is_raise = errors=='raise'
511514
bint is_ignore = errors=='ignore'
512515
bint is_coerce = errors=='coerce'
516+
bint is_same_offsets
513517
_TSObject _ts
518+
int64_t value
514519
int out_local=0, out_tzoffset=0
515-
float offset_seconds
520+
float offset_seconds, tz_offset
516521
set out_tzoffset_vals = set()
517522

518523
# specify error conditions
@@ -764,7 +769,7 @@ cpdef array_to_datetime(ndarray[object] values, errors='raise',
764769
@cython.wraparound(False)
765770
@cython.boundscheck(False)
766771
cdef array_to_datetime_object(ndarray[object] values, bint is_raise,
767-
dayfirst=False, yearfirst=False):
772+
bint dayfirst=False, bint yearfirst=False):
768773
"""
769774
Fall back function for array_to_datetime
770775

pandas/_libs/tslibs/conversion.pyx

+4-1
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,13 @@ def ensure_datetime64ns(arr: ndarray, copy: bool=True):
9999

100100
ivalues = arr.view(np.int64).ravel()
101101

102-
result = np.empty(shape, dtype='M8[ns]')
102+
result = np.empty(shape, dtype=NS_DTYPE)
103103
iresult = result.ravel().view(np.int64)
104104

105105
if len(iresult) == 0:
106+
result = arr.view(NS_DTYPE)
107+
if copy:
108+
result = result.copy()
106109
return result
107110

108111
unit = get_datetime64_unit(arr.flat[0])

pandas/conftest.py

+81-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from datetime import date, time, timedelta
2+
from decimal import Decimal
13
import importlib
24
import os
35

@@ -8,7 +10,7 @@
810
import pytest
911
from pytz import FixedOffset, utc
1012

11-
from pandas.compat import PY3
13+
from pandas.compat import PY3, u
1214
import pandas.util._test_decorators as td
1315

1416
import pandas as pd
@@ -514,6 +516,84 @@ def any_numpy_dtype(request):
514516
return request.param
515517

516518

519+
# categoricals are handled separately
520+
_any_skipna_inferred_dtype = [
521+
('string', ['a', np.nan, 'c']),
522+
('unicode' if not PY3 else 'string', [u('a'), np.nan, u('c')]),
523+
('bytes' if PY3 else 'string', [b'a', np.nan, b'c']),
524+
('empty', [np.nan, np.nan, np.nan]),
525+
('empty', []),
526+
('mixed-integer', ['a', np.nan, 2]),
527+
('mixed', ['a', np.nan, 2.0]),
528+
('floating', [1.0, np.nan, 2.0]),
529+
('integer', [1, np.nan, 2]),
530+
('mixed-integer-float', [1, np.nan, 2.0]),
531+
('decimal', [Decimal(1), np.nan, Decimal(2)]),
532+
('boolean', [True, np.nan, False]),
533+
('datetime64', [np.datetime64('2013-01-01'), np.nan,
534+
np.datetime64('2018-01-01')]),
535+
('datetime', [pd.Timestamp('20130101'), np.nan, pd.Timestamp('20180101')]),
536+
('date', [date(2013, 1, 1), np.nan, date(2018, 1, 1)]),
537+
# The following two dtypes are commented out due to GH 23554
538+
# ('complex', [1 + 1j, np.nan, 2 + 2j]),
539+
# ('timedelta64', [np.timedelta64(1, 'D'),
540+
# np.nan, np.timedelta64(2, 'D')]),
541+
('timedelta', [timedelta(1), np.nan, timedelta(2)]),
542+
('time', [time(1), np.nan, time(2)]),
543+
('period', [pd.Period(2013), pd.NaT, pd.Period(2018)]),
544+
('interval', [pd.Interval(0, 1), np.nan, pd.Interval(0, 2)])]
545+
ids, _ = zip(*_any_skipna_inferred_dtype) # use inferred type as fixture-id
546+
547+
548+
@pytest.fixture(params=_any_skipna_inferred_dtype, ids=ids)
549+
def any_skipna_inferred_dtype(request):
550+
"""
551+
Fixture for all inferred dtypes from _libs.lib.infer_dtype
552+
553+
The covered (inferred) types are:
554+
* 'string'
555+
* 'unicode' (if PY2)
556+
* 'empty'
557+
* 'bytes' (if PY3)
558+
* 'mixed'
559+
* 'mixed-integer'
560+
* 'mixed-integer-float'
561+
* 'floating'
562+
* 'integer'
563+
* 'decimal'
564+
* 'boolean'
565+
* 'datetime64'
566+
* 'datetime'
567+
* 'date'
568+
* 'timedelta'
569+
* 'time'
570+
* 'period'
571+
* 'interval'
572+
573+
Returns
574+
-------
575+
inferred_dtype : str
576+
The string for the inferred dtype from _libs.lib.infer_dtype
577+
values : np.ndarray
578+
An array of object dtype that will be inferred to have
579+
`inferred_dtype`
580+
581+
Examples
582+
--------
583+
>>> import pandas._libs.lib as lib
584+
>>>
585+
>>> def test_something(any_skipna_inferred_dtype):
586+
... inferred_dtype, values = any_skipna_inferred_dtype
587+
... # will pass
588+
... assert lib.infer_dtype(values, skipna=True) == inferred_dtype
589+
"""
590+
inferred_dtype, values = request.param
591+
values = np.array(values, dtype=object) # object dtype to avoid casting
592+
593+
# correctness of inference tested in tests/dtypes/test_inference.py
594+
return inferred_dtype, values
595+
596+
517597
@pytest.fixture
518598
def mock():
519599
"""

0 commit comments

Comments
 (0)