test_drop.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import warnings
  2. import numpy as np
  3. import pytest
  4. from pandas.errors import PerformanceWarning
  5. import pandas as pd
  6. from pandas import (
  7. Index,
  8. MultiIndex,
  9. )
  10. import pandas._testing as tm
  11. def test_drop(idx):
  12. dropped = idx.drop([("foo", "two"), ("qux", "one")])
  13. index = MultiIndex.from_tuples([("foo", "two"), ("qux", "one")])
  14. dropped2 = idx.drop(index)
  15. expected = idx[[0, 2, 3, 5]]
  16. tm.assert_index_equal(dropped, expected)
  17. tm.assert_index_equal(dropped2, expected)
  18. dropped = idx.drop(["bar"])
  19. expected = idx[[0, 1, 3, 4, 5]]
  20. tm.assert_index_equal(dropped, expected)
  21. dropped = idx.drop("foo")
  22. expected = idx[[2, 3, 4, 5]]
  23. tm.assert_index_equal(dropped, expected)
  24. index = MultiIndex.from_tuples([("bar", "two")])
  25. with pytest.raises(KeyError, match=r"^15$"):
  26. idx.drop([("bar", "two")])
  27. with pytest.raises(KeyError, match=r"^15$"):
  28. idx.drop(index)
  29. with pytest.raises(KeyError, match=r"^'two'$"):
  30. idx.drop(["foo", "two"])
  31. # partially correct argument
  32. mixed_index = MultiIndex.from_tuples([("qux", "one"), ("bar", "two")])
  33. with pytest.raises(KeyError, match=r"^15$"):
  34. idx.drop(mixed_index)
  35. # error='ignore'
  36. dropped = idx.drop(index, errors="ignore")
  37. expected = idx[[0, 1, 2, 3, 4, 5]]
  38. tm.assert_index_equal(dropped, expected)
  39. dropped = idx.drop(mixed_index, errors="ignore")
  40. expected = idx[[0, 1, 2, 3, 5]]
  41. tm.assert_index_equal(dropped, expected)
  42. dropped = idx.drop(["foo", "two"], errors="ignore")
  43. expected = idx[[2, 3, 4, 5]]
  44. tm.assert_index_equal(dropped, expected)
  45. # mixed partial / full drop
  46. dropped = idx.drop(["foo", ("qux", "one")])
  47. expected = idx[[2, 3, 5]]
  48. tm.assert_index_equal(dropped, expected)
  49. # mixed partial / full drop / error='ignore'
  50. mixed_index = ["foo", ("qux", "one"), "two"]
  51. with pytest.raises(KeyError, match=r"^'two'$"):
  52. idx.drop(mixed_index)
  53. dropped = idx.drop(mixed_index, errors="ignore")
  54. expected = idx[[2, 3, 5]]
  55. tm.assert_index_equal(dropped, expected)
  56. def test_droplevel_with_names(idx):
  57. index = idx[idx.get_loc("foo")]
  58. dropped = index.droplevel(0)
  59. assert dropped.name == "second"
  60. index = MultiIndex(
  61. levels=[Index(range(4)), Index(range(4)), Index(range(4))],
  62. codes=[
  63. np.array([0, 0, 1, 2, 2, 2, 3, 3]),
  64. np.array([0, 1, 0, 0, 0, 1, 0, 1]),
  65. np.array([1, 0, 1, 1, 0, 0, 1, 0]),
  66. ],
  67. names=["one", "two", "three"],
  68. )
  69. dropped = index.droplevel(0)
  70. assert dropped.names == ("two", "three")
  71. dropped = index.droplevel("two")
  72. expected = index.droplevel(1)
  73. assert dropped.equals(expected)
  74. def test_droplevel_list():
  75. index = MultiIndex(
  76. levels=[Index(range(4)), Index(range(4)), Index(range(4))],
  77. codes=[
  78. np.array([0, 0, 1, 2, 2, 2, 3, 3]),
  79. np.array([0, 1, 0, 0, 0, 1, 0, 1]),
  80. np.array([1, 0, 1, 1, 0, 0, 1, 0]),
  81. ],
  82. names=["one", "two", "three"],
  83. )
  84. dropped = index[:2].droplevel(["three", "one"])
  85. expected = index[:2].droplevel(2).droplevel(0)
  86. assert dropped.equals(expected)
  87. dropped = index[:2].droplevel([])
  88. expected = index[:2]
  89. assert dropped.equals(expected)
  90. msg = (
  91. "Cannot remove 3 levels from an index with 3 levels: "
  92. "at least one level must be left"
  93. )
  94. with pytest.raises(ValueError, match=msg):
  95. index[:2].droplevel(["one", "two", "three"])
  96. with pytest.raises(KeyError, match="'Level four not found'"):
  97. index[:2].droplevel(["one", "four"])
  98. def test_drop_not_lexsorted():
  99. # GH 12078
  100. # define the lexsorted version of the multi-index
  101. tuples = [("a", ""), ("b1", "c1"), ("b2", "c2")]
  102. lexsorted_mi = MultiIndex.from_tuples(tuples, names=["b", "c"])
  103. assert lexsorted_mi._is_lexsorted()
  104. # and the not-lexsorted version
  105. df = pd.DataFrame(
  106. columns=["a", "b", "c", "d"], data=[[1, "b1", "c1", 3], [1, "b2", "c2", 4]]
  107. )
  108. df = df.pivot_table(index="a", columns=["b", "c"], values="d")
  109. df = df.reset_index()
  110. not_lexsorted_mi = df.columns
  111. assert not not_lexsorted_mi._is_lexsorted()
  112. # compare the results
  113. tm.assert_index_equal(lexsorted_mi, not_lexsorted_mi)
  114. with tm.assert_produces_warning(PerformanceWarning):
  115. tm.assert_index_equal(lexsorted_mi.drop("a"), not_lexsorted_mi.drop("a"))
  116. def test_drop_with_nan_in_index(nulls_fixture):
  117. # GH#18853
  118. mi = MultiIndex.from_tuples([("blah", nulls_fixture)], names=["name", "date"])
  119. msg = r"labels \[Timestamp\('2001-01-01 00:00:00'\)\] not found in level"
  120. with pytest.raises(KeyError, match=msg):
  121. mi.drop(pd.Timestamp("2001"), level="date")
  122. def test_drop_with_non_monotonic_duplicates():
  123. # GH#33494
  124. mi = MultiIndex.from_tuples([(1, 2), (2, 3), (1, 2)])
  125. with warnings.catch_warnings():
  126. warnings.simplefilter("ignore", PerformanceWarning)
  127. result = mi.drop((1, 2))
  128. expected = MultiIndex.from_tuples([(2, 3)])
  129. tm.assert_index_equal(result, expected)
  130. def test_single_level_drop_partially_missing_elements():
  131. # GH 37820
  132. mi = MultiIndex.from_tuples([(1, 2), (2, 2), (3, 2)])
  133. msg = r"labels \[4\] not found in level"
  134. with pytest.raises(KeyError, match=msg):
  135. mi.drop(4, level=0)
  136. with pytest.raises(KeyError, match=msg):
  137. mi.drop([1, 4], level=0)
  138. msg = r"labels \[nan\] not found in level"
  139. with pytest.raises(KeyError, match=msg):
  140. mi.drop([np.nan], level=0)
  141. with pytest.raises(KeyError, match=msg):
  142. mi.drop([np.nan, 1, 2, 3], level=0)
  143. mi = MultiIndex.from_tuples([(np.nan, 1), (1, 2)])
  144. msg = r"labels \['a'\] not found in level"
  145. with pytest.raises(KeyError, match=msg):
  146. mi.drop([np.nan, 1, "a"], level=0)
  147. def test_droplevel_multiindex_one_level():
  148. # GH#37208
  149. index = MultiIndex.from_tuples([(2,)], names=("b",))
  150. result = index.droplevel([])
  151. expected = Index([2], name="b")
  152. tm.assert_index_equal(result, expected)