style.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. # being a bit too dynamic
  2. import warnings
  3. import matplotlib.cm as cm
  4. import matplotlib.colors
  5. import numpy as np
  6. from pandas.core.dtypes.common import is_list_like
  7. import pandas.core.common as com
  8. def _get_standard_colors(
  9. num_colors=None, colormap=None, color_type="default", color=None
  10. ):
  11. import matplotlib.pyplot as plt
  12. if color is None and colormap is not None:
  13. if isinstance(colormap, str):
  14. cmap = colormap
  15. colormap = cm.get_cmap(colormap)
  16. if colormap is None:
  17. raise ValueError(f"Colormap {cmap} is not recognized")
  18. colors = [colormap(num) for num in np.linspace(0, 1, num=num_colors)]
  19. elif color is not None:
  20. if colormap is not None:
  21. warnings.warn(
  22. "'color' and 'colormap' cannot be used simultaneously. Using 'color'"
  23. )
  24. colors = list(color) if is_list_like(color) else color
  25. else:
  26. if color_type == "default":
  27. # need to call list() on the result to copy so we don't
  28. # modify the global rcParams below
  29. try:
  30. colors = [c["color"] for c in list(plt.rcParams["axes.prop_cycle"])]
  31. except KeyError:
  32. colors = list(plt.rcParams.get("axes.color_cycle", list("bgrcmyk")))
  33. if isinstance(colors, str):
  34. colors = list(colors)
  35. colors = colors[0:num_colors]
  36. elif color_type == "random":
  37. def random_color(column):
  38. """ Returns a random color represented as a list of length 3"""
  39. # GH17525 use common._random_state to avoid resetting the seed
  40. rs = com.random_state(column)
  41. return rs.rand(3).tolist()
  42. colors = [random_color(num) for num in range(num_colors)]
  43. else:
  44. raise ValueError("color_type must be either 'default' or 'random'")
  45. if isinstance(colors, str):
  46. conv = matplotlib.colors.ColorConverter()
  47. def _maybe_valid_colors(colors):
  48. try:
  49. [conv.to_rgba(c) for c in colors]
  50. return True
  51. except ValueError:
  52. return False
  53. # check whether the string can be convertible to single color
  54. maybe_single_color = _maybe_valid_colors([colors])
  55. # check whether each character can be convertible to colors
  56. maybe_color_cycle = _maybe_valid_colors(list(colors))
  57. if maybe_single_color and maybe_color_cycle and len(colors) > 1:
  58. hex_color = [c["color"] for c in list(plt.rcParams["axes.prop_cycle"])]
  59. colors = [hex_color[int(colors[1])]]
  60. elif maybe_single_color:
  61. colors = [colors]
  62. else:
  63. # ``colors`` is regarded as color cycle.
  64. # mpl will raise error any of them is invalid
  65. pass
  66. # Append more colors by cycling if there is not enough color.
  67. # Extra colors will be ignored by matplotlib if there are more colors
  68. # than needed and nothing needs to be done here.
  69. if len(colors) < num_colors:
  70. try:
  71. multiple = num_colors // len(colors) - 1
  72. except ZeroDivisionError:
  73. raise ValueError("Invalid color argument: ''")
  74. mod = num_colors % len(colors)
  75. colors += multiple * colors
  76. colors += colors[:mod]
  77. return colors