Skip to content

Commit 944cf96

Browse files
author
tp
committed
DataFrame.append preserves columns dtype if possible
1 parent b9da33c commit 944cf96

File tree

2 files changed

+26
-42
lines changed

2 files changed

+26
-42
lines changed

doc/source/whatsnew/v0.23.0.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ Other Enhancements
315315
- ``Resampler`` objects now have a functioning :attr:`~pandas.core.resample.Resampler.pipe` method.
316316
Previously, calls to ``pipe`` were diverted to the ``mean`` method (:issue:`17905`).
317317
- :func:`~pandas.api.types.is_scalar` now returns ``True`` for ``DateOffset`` objects (:issue:`18943`).
318+
- :meth:`DataFrame.append` now preserves the type of the calling dataframe's columns, when possible (:issue:`18359`)
318319
- Added :func:`pandas.api.extensions.register_dataframe_accessor`,
319320
:func:`pandas.api.extensions.register_series_accessor`, and
320321
:func:`pandas.api.extensions.register_index_accessor`, accessor for libraries downstream of pandas
@@ -324,7 +325,6 @@ Other Enhancements
324325
- ``IntervalIndex.astype`` now supports conversions between subtypes when passed an ``IntervalDtype`` (:issue:`19197`)
325326
- :class:`IntervalIndex` and its associated constructor methods (``from_arrays``, ``from_breaks``, ``from_tuples``) have gained a ``dtype`` parameter (:issue:`19262`)
326327
- Added :func:`SeriesGroupBy.is_monotonic_increasing` and :func:`SeriesGroupBy.is_monotonic_decreasing` (:issue:`17015`)
327-
- :meth:`DataFrame.append` now preserves the type of the calling dataframe's columns, when possible (:issue:`18359`)
328328

329329
.. _whatsnew_0230.api_breaking:
330330

pandas/tests/reshape/test_concat.py

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -833,14 +833,15 @@ def test_append_preserve_index_name(self):
833833

834834
@pytest.mark.parametrize("df_columns", [
835835
pd.RangeIndex(3),
836+
pd.Index([1, 2, 3]),
837+
pd.Index(list('abc')),
836838
pd.CategoricalIndex('A B C'.split()),
837839
pd.CategoricalIndex('A B C'.split(), ordered=True),
838840
pd.MultiIndex.from_arrays(['A B C'.split(), 'D E F'.split()]),
839841
pd.IntervalIndex.from_breaks([0, 1, 2, 3]),
840842
pd.DatetimeIndex([dt.datetime(2013, 1, 3, 0, 0),
841843
dt.datetime(2013, 1, 3, 6, 10),
842844
dt.datetime(2013, 1, 3, 7, 12)]),
843-
pd.Index([1, 2, 3]),
844845
], ids=lambda x: str(x.dtype))
845846
def test_append_same_columns_type(self, df_columns):
846847
# GH18359
@@ -870,16 +871,16 @@ def test_append_same_columns_type(self, df_columns):
870871
pd.RangeIndex(3),
871872
pd.Index([4, 5, 6]),
872873
pd.Index([7.5, 8.5, 9.5]),
873-
pd.CategoricalIndex('A B C'.split()),
874-
# pd.CategoricalIndex('A B C'.split(), ordered=True),
874+
pd.Index(list('abc')),
875+
pd.CategoricalIndex('A B C'.split(), ordered=True),
876+
# pd.CategoricalIndex('A B C'.split()),
875877
pd.DatetimeIndex([dt.datetime(2013, 1, 3, 0, 0),
876878
dt.datetime(2013, 1, 3, 6, 10),
877879
dt.datetime(2013, 1, 3, 7, 12)]),
878880
], r=2), ids=lambda x: str(x.dtype))
879881
def test_append_different_columns_types(self, df_columns, series_index):
880882
# GH18359
881-
# see also tests 'test_append_multi_index_raises' and
882-
# 'test_append_interval_index_raises' below
883+
# see also test 'test_append_different_columns_types_raises' below
883884

884885
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=df_columns)
885886
ser = pd.Series([7, 8, 9], index=series_index, name=2)
@@ -894,60 +895,43 @@ def test_append_different_columns_types(self, df_columns, series_index):
894895
columns=combined_columns)
895896
assert_frame_equal(result, expected)
896897

897-
@pytest.mark.parametrize("other_type", [
898-
pd.RangeIndex(3),
899-
pd.CategoricalIndex('A B C'.split()),
900-
pd.CategoricalIndex('A B C'.split(), ordered=True),
898+
@pytest.mark.parametrize("this_type", [
901899
pd.IntervalIndex.from_breaks([0, 1, 2, 3]),
902-
pd.DatetimeIndex([dt.datetime(2013, 1, 3, 0, 0),
903-
dt.datetime(2013, 1, 3, 6, 10),
904-
dt.datetime(2013, 1, 3, 7, 12)]),
905-
pd.Index([4, 5, 6]),
906-
], ids=lambda x: str(x.dtype))
907-
def test_append_multi_index_raises(self, other_type):
908-
# GH18359
909-
# .append will raise if MultiIndex appends or is appended to a
910-
# different index type
911-
912-
mi = pd.MultiIndex.from_arrays(['A B C'.split(), 'D E F'.split()])
913-
914-
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=mi)
915-
ser = pd.Series([7, 8, 9], index=other_type, name=2)
916-
if isinstance(other_type, pd.IntervalIndex):
917-
pytest.raises(ValueError, df.append, ser)
918-
else:
919-
pytest.raises(TypeError, df.append, ser)
920-
921-
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=other_type)
922-
ser = pd.Series([7, 8, 9], index=mi, name=2)
923-
with pytest.raises(TypeError):
924-
df.append(ser)
925-
900+
pd.MultiIndex.from_arrays(['A B C'.split(), 'D E F'.split()]),
901+
])
926902
@pytest.mark.parametrize("other_type", [
927903
pd.RangeIndex(3),
904+
pd.Index([4, 5, 6]),
905+
pd.Index(list("abc")),
928906
pd.CategoricalIndex('A B C'.split()),
929907
pd.CategoricalIndex('A B C'.split(), ordered=True),
908+
pd.IntervalIndex.from_breaks([0, 1, 2, 3]),
930909
pd.MultiIndex.from_arrays(['A B C'.split(), 'D E F'.split()]),
931910
pd.DatetimeIndex([dt.datetime(2013, 1, 3, 0, 0),
932911
dt.datetime(2013, 1, 3, 6, 10),
933912
dt.datetime(2013, 1, 3, 7, 12)]),
934-
pd.Index([4, 5, 6]),
935913
], ids=lambda x: str(x.dtype))
936-
def test_append_interval_index_raises(self, other_type):
914+
def test_append_different_columns_types_raises(self,
915+
this_type, other_type):
937916
# GH18359
938-
# .append will raise if IntervalIndex appends or is appended to a
939-
# different index type
917+
# .append will raise if IntervalIndex/MultiIndex appends or is
918+
# appended to a different index type
919+
#
920+
# see also test 'test_append_different_columns_types' above for
921+
# appending without raising.
940922

941-
ii = pd.IntervalIndex.from_breaks([0, 1, 2, 3])
923+
if type(this_type) is type(other_type):
924+
# don't test same type
925+
return
942926

943-
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=ii)
927+
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=this_type)
944928
ser = pd.Series([7, 8, 9], index=other_type, name=2)
945929
with pytest.raises(TypeError):
946930
df.append(ser)
947931

948932
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=other_type)
949-
ser = pd.Series([7, 8, 9], index=ii, name=2)
950-
with pytest.raises(ValueError):
933+
ser = pd.Series([7, 8, 9], index=this_type, name=2)
934+
with pytest.raises(TypeError):
951935
df.append(ser)
952936

953937
def test_append_dtype_coerce(self):

0 commit comments

Comments
 (0)