Skip to content

Commit 89871a0

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 4f16c8b + 99df7da commit 89871a0

30 files changed

+1791
-1367
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ build: clean_pyc
1313
python setup.py build_ext --inplace
1414

1515
lint-diff:
16-
git diff master --name-only -- "*.py" | grep -E "pandas|scripts" | xargs flake8
16+
git diff upstream/master --name-only -- "*.py" | xargs flake8
1717

1818
develop: build
1919
-python setup.py develop

ci/deps/travis-36-doc.yaml

-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ name: pandas
22
channels:
33
- defaults
44
- conda-forge
5-
- r
65
dependencies:
76
- beautifulsoup4
87
- bottleneck
@@ -31,14 +30,11 @@ dependencies:
3130
- python-snappy
3231
- python=3.6*
3332
- pytz
34-
- r
35-
- rpy2
3633
- scipy
3734
- seaborn
3835
- sphinx
3936
- sqlalchemy
4037
- statsmodels
41-
- tzlocal
4238
- xarray
4339
- xlrd
4440
- xlsxwriter

doc/source/contributing.rst

+9-9
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ the `flake8 <https://pypi.org/project/flake8>`_ tool
575575
and report any stylistic errors in your code. Therefore, it is helpful before
576576
submitting code to run the check yourself on the diff::
577577

578-
git diff master -u -- "*.py" | flake8 --diff
578+
git diff upstream/master -u -- "*.py" | flake8 --diff
579579

580580
This command will catch any stylistic errors in your changes specifically, but
581581
be beware it may not catch all of them. For example, if you delete the only
@@ -584,21 +584,21 @@ unused function. However, style-checking the diff will not catch this because
584584
the actual import is not part of the diff. Thus, for completeness, you should
585585
run this command, though it will take longer::
586586

587-
git diff master --name-only -- "*.py" | grep "pandas/" | xargs -r flake8
587+
git diff upstream/master --name-only -- "*.py" | xargs -r flake8
588588

589589
Note that on OSX, the ``-r`` flag is not available, so you have to omit it and
590590
run this slightly modified command::
591591

592-
git diff master --name-only -- "*.py" | grep "pandas/" | xargs flake8
592+
git diff upstream/master --name-only -- "*.py" | xargs flake8
593593

594-
Windows does not support the ``grep`` and ``xargs`` commands (unless installed
595-
for example via the `MinGW <http://www.mingw.org/>`__ toolchain), but one can
596-
imitate the behaviour as follows::
594+
Windows does not support the ``xargs`` command (unless installed for example
595+
via the `MinGW <http://www.mingw.org/>`__ toolchain), but one can imitate the
596+
behaviour as follows::
597597

598-
for /f %i in ('git diff upstream/master --name-only ^| findstr pandas/') do flake8 %i
598+
for /f %i in ('git diff upstream/master --name-only -- "*.py"') do flake8 %i
599599

600-
This will also get all the files being changed by the PR (and within the
601-
``pandas/`` folder), and run ``flake8`` on them one after the other.
600+
This will get all the files being changed by the PR (and ending with ``.py``),
601+
and run ``flake8`` on them, one after the other.
602602

603603
.. _contributing.import-formatting:
604604

doc/source/r_interface.rst

+25-12
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,28 @@ See also the documentation of the `rpy2 <http://rpy2.bitbucket.org/>`__ project:
3333

3434
In the remainder of this page, a few examples of explicit conversion is given. The pandas conversion of rpy2 needs first to be activated:
3535

36-
.. ipython:: python
36+
.. code-block:: python
3737
38-
from rpy2.robjects import r, pandas2ri
39-
pandas2ri.activate()
38+
>>> from rpy2.robjects import pandas2ri # doctest: +SKIP
39+
>>> pandas2ri.activate() # doctest: +SKIP
4040
4141
Transferring R data sets into Python
4242
------------------------------------
4343

4444
Once the pandas conversion is activated (``pandas2ri.activate()``), many conversions
4545
of R to pandas objects will be done automatically. For example, to obtain the 'iris' dataset as a pandas DataFrame:
4646

47-
.. ipython:: python
47+
.. code-block:: python
4848
49-
r.data('iris')
50-
r['iris'].head()
49+
>>> from rpy2.robjects import r # doctest: +SKIP
50+
>>> r.data('iris') # doctest: +SKIP
51+
>>> r['iris'].head() # doctest: +SKIP
52+
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
53+
0 5.1 3.5 1.4 0.2 setosa
54+
1 4.9 3.0 1.4 0.2 setosa
55+
2 4.7 3.2 1.3 0.2 setosa
56+
3 4.6 3.1 1.5 0.2 setosa
57+
4 5.0 3.6 1.4 0.2 setosa
5158
5259
If the pandas conversion was not activated, the above could also be accomplished
5360
by explicitly converting it with the ``pandas2ri.ri2py`` function
@@ -59,13 +66,19 @@ Converting DataFrames into R objects
5966
The ``pandas2ri.py2ri`` function support the reverse operation to convert
6067
DataFrames into the equivalent R object (that is, **data.frame**):
6168

62-
.. ipython:: python
69+
.. code-block:: python
70+
71+
>>> df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]},
72+
... index=["one", "two", "three"]) # doctest: +SKIP
73+
>>> r_dataframe = pandas2ri.py2ri(df) # doctest: +SKIP
74+
>>> print(type(r_dataframe)) # doctest: +SKIP
75+
<class 'rpy2.robjects.vectors.DataFrame'>
76+
>>> print(r_dataframe) # doctest: +SKIP
77+
A B C
78+
one 1 4 7
79+
two 2 5 8
80+
three 3 6 9
6381
64-
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C':[7,8,9]},
65-
index=["one", "two", "three"])
66-
r_dataframe = pandas2ri.py2ri(df)
67-
print(type(r_dataframe))
68-
print(r_dataframe)
6982
7083
The DataFrame's index is stored as the ``rownames`` attribute of the
7184
data.frame instance.

doc/source/whatsnew/v0.24.0.rst

+4
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ For situations where you need an ``ndarray`` of ``Interval`` objects, use
466466
np.asarray(idx)
467467
idx.values.astype(object)
468468
469+
469470
.. _whatsnew_0240.api.timezone_offset_parsing:
470471

471472
Parsing Datetime Strings with Timezone Offsets
@@ -1442,6 +1443,7 @@ Reshaping
14421443
- Bug in :func:`merge_asof` where confusing error message raised when attempting to merge with missing values (:issue:`23189`)
14431444
- Bug in :meth:`DataFrame.nsmallest` and :meth:`DataFrame.nlargest` for dataframes that have a :class:`MultiIndex` for columns (:issue:`23033`).
14441445
- Bug in :meth:`DataFrame.append` with a :class:`Series` with a dateutil timezone would raise a ``TypeError`` (:issue:`23682`)
1446+
- Bug in ``Series`` construction when passing no data and ``dtype=str`` (:issue:`22477`)
14451447

14461448
.. _whatsnew_0240.bug_fixes.sparse:
14471449

@@ -1474,6 +1476,7 @@ Other
14741476
- :meth:`DataFrame.nlargest` and :meth:`DataFrame.nsmallest` now returns the correct n values when keep != 'all' also when tied on the first columns (:issue:`22752`)
14751477
- :meth:`~pandas.io.formats.style.Styler.bar` now also supports tablewise application (in addition to rowwise and columnwise) with ``axis=None`` and setting clipping range with ``vmin`` and ``vmax`` (:issue:`21548` and :issue:`21526`). ``NaN`` values are also handled properly.
14761478
- Logical operations ``&, |, ^`` between :class:`Series` and :class:`Index` will no longer raise ``ValueError`` (:issue:`22092`)
1479+
- Checking PEP 3141 numbers in :func:`~pandas.api.types.is_scalar` function returns ``True`` (:issue:`22903`)
14771480
- Bug in :meth:`DataFrame.combine_first` in which column types were unexpectedly converted to float (:issue:`20699`)
14781481

14791482
.. _whatsnew_0.24.0.contributors:
@@ -1482,3 +1485,4 @@ Contributors
14821485
~~~~~~~~~~~~
14831486

14841487
.. contributors:: v0.23.4..HEAD
1488+

pandas/_libs/lib.pyx

+46-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# -*- coding: utf-8 -*-
22
from decimal import Decimal
3+
from fractions import Fraction
4+
from numbers import Number
5+
36
import sys
47

58
import cython
@@ -15,7 +18,6 @@ from cpython.datetime cimport (PyDateTime_Check, PyDate_Check,
1518
PyDateTime_IMPORT)
1619
PyDateTime_IMPORT
1720

18-
1921
import numpy as np
2022
cimport numpy as cnp
2123
from numpy cimport (ndarray, PyArray_GETITEM,
@@ -105,23 +107,54 @@ def is_scalar(val: object) -> bool:
105107
"""
106108
Return True if given value is scalar.
107109

108-
This includes:
109-
- numpy array scalar (e.g. np.int64)
110-
- Python builtin numerics
111-
- Python builtin byte arrays and strings
112-
- None
113-
- instances of datetime.datetime
114-
- instances of datetime.timedelta
115-
- Period
116-
- instances of decimal.Decimal
117-
- Interval
118-
- DateOffset
110+
Parameters
111+
----------
112+
val : object
113+
This includes:
114+
115+
- numpy array scalar (e.g. np.int64)
116+
- Python builtin numerics
117+
- Python builtin byte arrays and strings
118+
- None
119+
- datetime.datetime
120+
- datetime.timedelta
121+
- Period
122+
- decimal.Decimal
123+
- Interval
124+
- DateOffset
125+
- Fraction
126+
- Number
127+
128+
Returns
129+
-------
130+
bool
131+
Return True if given object is scalar, False otherwise
132+
133+
Examples
134+
--------
135+
>>> dt = pd.datetime.datetime(2018, 10, 3)
136+
>>> pd.is_scalar(dt)
137+
True
138+
139+
>>> pd.api.types.is_scalar([2, 3])
140+
False
141+
142+
>>> pd.api.types.is_scalar({0: 1, 2: 3})
143+
False
144+
145+
>>> pd.api.types.is_scalar((0, 2))
146+
False
147+
148+
pandas supports PEP 3141 numbers:
119149

150+
>>> from fractions import Fraction
151+
>>> pd.api.types.is_scalar(Fraction(3, 5))
152+
True
120153
"""
121154

122155
return (cnp.PyArray_IsAnyScalar(val)
123156
# As of numpy-1.9, PyArray_IsAnyScalar misses bytearrays on Py3.
124-
or isinstance(val, bytes)
157+
or isinstance(val, (bytes, Fraction, Number))
125158
# We differ from numpy (as of 1.10), which claims that None is
126159
# not scalar in np.isscalar().
127160
or val is None

pandas/core/arrays/timedeltas.py

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# -*- coding: utf-8 -*-
2+
from __future__ import division
3+
24
from datetime import timedelta
5+
import operator
36
import warnings
47

58
import numpy as np
@@ -16,9 +19,11 @@
1619
_TD_DTYPE, ensure_int64, is_datetime64_dtype, is_float_dtype,
1720
is_integer_dtype, is_list_like, is_object_dtype, is_string_dtype,
1821
is_timedelta64_dtype)
19-
from pandas.core.dtypes.generic import ABCSeries, ABCTimedeltaIndex
22+
from pandas.core.dtypes.generic import (
23+
ABCDataFrame, ABCIndexClass, ABCSeries, ABCTimedeltaIndex)
2024
from pandas.core.dtypes.missing import isna
2125

26+
from pandas.core import ops
2227
from pandas.core.algorithms import checked_add_with_arr
2328
import pandas.core.common as com
2429

@@ -101,8 +106,32 @@ def wrapper(self, other):
101106
return compat.set_function_name(wrapper, opname, cls)
102107

103108

109+
def _wrap_tdi_op(op):
110+
"""
111+
Instead of re-implementing multiplication/division etc operations
112+
in the Array class, for now we dispatch to the TimedeltaIndex
113+
implementations.
114+
"""
115+
# TODO: implement directly here and wrap in TimedeltaIndex, instead of
116+
# the other way around
117+
def method(self, other):
118+
if isinstance(other, (ABCSeries, ABCDataFrame, ABCIndexClass)):
119+
return NotImplemented
120+
121+
from pandas import TimedeltaIndex
122+
obj = TimedeltaIndex(self)
123+
result = op(obj, other)
124+
if is_timedelta64_dtype(result):
125+
return type(self)(result)
126+
return np.array(result)
127+
128+
method.__name__ = '__{name}__'.format(name=op.__name__)
129+
return method
130+
131+
104132
class TimedeltaArrayMixin(dtl.DatetimeLikeArrayMixin):
105133
_typ = "timedeltaarray"
134+
__array_priority__ = 1000
106135

107136
@property
108137
def _box_func(self):
@@ -293,11 +322,25 @@ def _evaluate_with_timedelta_like(self, other, op):
293322

294323
return NotImplemented
295324

325+
__mul__ = _wrap_tdi_op(operator.mul)
326+
__rmul__ = __mul__
327+
__truediv__ = _wrap_tdi_op(operator.truediv)
328+
__floordiv__ = _wrap_tdi_op(operator.floordiv)
329+
__rfloordiv__ = _wrap_tdi_op(ops.rfloordiv)
330+
331+
if compat.PY2:
332+
__div__ = __truediv__
333+
334+
# Note: TimedeltaIndex overrides this in call to cls._add_numeric_methods
296335
def __neg__(self):
297336
if self.freq is not None:
298337
return type(self)(-self._data, freq=-self.freq)
299338
return type(self)(-self._data)
300339

340+
def __abs__(self):
341+
# Note: freq is not preserved
342+
return type(self)(np.abs(self._data))
343+
301344
# ----------------------------------------------------------------
302345
# Conversion Methods - Vectorized analogues of Timedelta methods
303346

pandas/core/dtypes/cast.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from pandas._libs import lib, tslib, tslibs
88
from pandas._libs.tslibs import OutOfBoundsDatetime, Period, iNaT
9-
from pandas.compat import PY3, string_types, text_type
9+
from pandas.compat import PY3, string_types, text_type, to_str
1010

1111
from .common import (
1212
_INT64_DTYPE, _NS_DTYPE, _POSSIBLY_CAST_DTYPES, _TD_DTYPE, _string_dtypes,
@@ -1216,11 +1216,16 @@ def construct_1d_arraylike_from_scalar(value, length, dtype):
12161216
if not isinstance(dtype, (np.dtype, type(np.dtype))):
12171217
dtype = dtype.dtype
12181218

1219-
# coerce if we have nan for an integer dtype
1220-
# GH 22858: only cast to float if an index
1221-
# (passed here as length) is specified
12221219
if length and is_integer_dtype(dtype) and isna(value):
1223-
dtype = np.float64
1220+
# coerce if we have nan for an integer dtype
1221+
dtype = np.dtype('float64')
1222+
elif isinstance(dtype, np.dtype) and dtype.kind in ("U", "S"):
1223+
# we need to coerce to object dtype to avoid
1224+
# to allow numpy to take our string as a scalar value
1225+
dtype = object
1226+
if not isna(value):
1227+
value = to_str(value)
1228+
12241229
subarr = np.empty(length, dtype=dtype)
12251230
subarr.fill(value)
12261231

pandas/core/dtypes/common.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ def is_datetime64_dtype(arr_or_dtype):
419419
return False
420420
try:
421421
tipo = _get_dtype_type(arr_or_dtype)
422-
except TypeError:
422+
except (TypeError, UnicodeEncodeError):
423423
return False
424424
return issubclass(tipo, np.datetime64)
425425

0 commit comments

Comments
 (0)