Skip to content

Coloring scatter plots by factor/string #11422

Open

Description

@kasuteru

Bug report

This may be either a bug report or a feature request, depending how you view things. The issue is that you cannot use a factor/string column in a pandas dataframe as color option without awkward workarounds.

Code for reproduction

data = pd.DataFrame(data={"x":[1,2,3,2,4], "y":[2,1,2,3,1], "z":["a", "b", "b", "a", "c"]})

plt.scatter(x="x", y="y", data=data)  # This works as nicely and as expected
plt.scatter(x="x", y="y", c="z", data=data) # This throws the following error:

Actual outcome

ValueError: c of shape (5,) not acceptable as a color sequence for x with size 5, y with size 5

Expected outcome
An image where each point is colored according to it's value in "z", cycling through a predefined color map. A shining example of how easy such a commonly used visualization should be is ggplot, see the code in this post: The color option automatically notices that this is a factor variable and assigns each level a color. Also, a legend is automatically shown.

Matplotlib version
'2.1.0'

Activity

  1. kasuteru commented on Jun 12, 2018

    @kasuteru
    Author

    After checking the documentation again, this is definitely a feature request. After seeing how many posts on stackoverflow are about exactly this problem, I think this is something that is really not working as expected - Intuition (and implementations in R and, for example, seaborn), suggest that matplotlib should automatically deduce what the user wants in this case instead of throwing an error.

  2. jklymak commented on Jun 12, 2018

    @jklymak
    Member

    OK, if you do data={"x":[1,2,3,2,4], "y":[2,1,2,3,1], "z":[5, 4, 3, 2, 1]} this works, right? We don't have categorical data for the z axis.

  3. kasuteru commented on Jun 12, 2018

    @kasuteru
    Author
  4. kasuteru commented on Jun 12, 2018

    @kasuteru
    Author
  5. jklymak commented on Jun 12, 2018

    @jklymak
    Member

    Yes, right now categorical axes work by converting the string "units" to numbers. But we don't have the equivalent unit conversion machinery in place for z-data. I think one of the reasons seaborn is around is to scratch that itch. We are thinking about how to do it, lead by @story645, but its not trivial.

  6. added this to the v3.1 milestone on Jun 12, 2018
  7. ImportanceOfBeingErnest commented on Jun 12, 2018

    @ImportanceOfBeingErnest
    Member

    This is how I would currently do it:

    data = pd.DataFrame(data={"x":[1,2,3,2,4], "y":[2,1,2,3,1], "z":["a", "b", "b", "a", "c"]})
    labels, data["znum"] = np.unique(data.z, return_inverse=True)
    
    scatter = plt.scatter(x="x", y="y", c="znum", data=data)
    

    Concerning the legend, there is a proposal #11127 which is still under review to simplify the legend creation. If this passes as in its current proposed version, a legend could be simply created like

    plt.legend(scatter.legend_elements()[0],labels)
    

    However, as of now you would need to create the legend manually, e.g. like

    handle = lambda c : plt.Line2D([0],[0], ls="", marker="o", color=scatter.cmap(scatter.norm(c)))
    handles = [handle(c) for c in np.unique(data.znum)]
    plt.legend(handles, labels)
    
  8. ImportanceOfBeingErnest commented on Jun 13, 2018

    @ImportanceOfBeingErnest
    Member

    Xref: This request is also very similar to the request in #6214.

  9. kasuteru commented on Jun 13, 2018

    @kasuteru
    Author

    @ImportanceOfBeingErnest : That indeed seems to be the same issue, with broader scope.

  10. modified the milestones: v3.1.0, v3.2.0 on Feb 4, 2019
  11. modified the milestones: v3.2.0, on Aug 11, 2019
  12. modified the milestones: , needs sorting on Oct 6, 2022
  13. github-actions commented on Oct 11, 2023

    @github-actions

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  14. story645 commented on Oct 11, 2023

    @story645
    Member

    I think this is still wanted and I think one way to tackle this is to try and make NoNorm unit aware #7383

  15. github-actions commented on Oct 11, 2024

    @github-actions

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  16. added
    keepItems to be ignored by the “Stale” Github Action
    and removed
    status: inactiveMarked by the “Stale” Github Action
    on Oct 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions