【问题标题】:Color by Column Values in MatplotlibMatplotlib 中按列值着色
【发布时间】:2013-01-30 21:47:52
【问题描述】:

我最喜欢在 R 中使用 ggplot2 库的一个方面是能够轻松指定美学。我可以快速制作一个散点图并应用与特定列相关的颜色,我希望能够使用 python/pandas/matplotlib 来做到这一点。我想知道是否有任何方便的函数可以让人们使用 pandas 数据框和 Matplotlib 将颜色映射到值?

##ggplot scatterplot example with R dataframe, `df`, colored by col3
ggplot(data = df, aes(x=col1, y=col2, color=col3)) + geom_point()

##ideal situation with pandas dataframe, 'df', where colors are chosen by col3
df.plot(x=col1,y=col2,color=col3)

编辑: 感谢您的回复,但我想包含一个示例数据框来澄清我的要求。两列包含数字数据,第三列是分类变量。我正在考虑的脚本将根据此值分配颜色。

np.random.seed(250)
df = pd.DataFrame({'Height': np.append(np.random.normal(6, 0.25, size=5), np.random.normal(5.4, 0.25, size=5)),
                   'Weight': np.append(np.random.normal(180, 20, size=5), np.random.normal(140, 20, size=5)),
                   'Gender': ["Male","Male","Male","Male","Male",
                              "Female","Female","Female","Female","Female"]})

     Height      Weight  Gender
0  5.824970  159.210508    Male
1  5.780403  180.294943    Male
2  6.318295  199.142201    Male
3  5.617211  157.813278    Male
4  6.340892  191.849944    Male
5  5.625131  139.588467  Female
6  4.950479  146.711220  Female
7  5.617245  121.571890  Female
8  5.556821  141.536028  Female
9  5.714171  134.396203  Female

【问题讨论】:

    标签: python pandas matplotlib seaborn


    【解决方案1】:

    进口和数据

    import numpy 
    import pandas
    import matplotlib.pyplot as plt
    import seaborn
    seaborn.set(style='ticks')
    
    numpy.random.seed(0)
    N = 37
    _genders= ['Female', 'Male', 'Non-binary', 'No Response']
    df = pandas.DataFrame({
        'Height (cm)': numpy.random.uniform(low=130, high=200, size=N),
        'Weight (kg)': numpy.random.uniform(low=30, high=100, size=N),
        'Gender': numpy.random.choice(_genders, size=N)
    })
    

    2021 年 8 月更新

    seaborn.relplot(data=df, x='Weight (kg)', y='Height (cm)', hue='Gender', hue_order=_genders, aspect=1.61)
    plt.show()
    

    2015 年 10 月更新

    Seaborn 出色地处理了这个用例:

    fg = seaborn.FacetGrid(data=df, hue='Gender', hue_order=_genders, aspect=1.61)
    fg.map(plt.scatter, 'Weight (kg)', 'Height (cm)').add_legend()
    

    立即输出:

    旧答案

    在这种情况下,我会直接使用 matplotlib。

    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    
    def dfScatter(df, xcol='Height', ycol='Weight', catcol='Gender'):
        fig, ax = plt.subplots()
        categories = np.unique(df[catcol])
        colors = np.linspace(0, 1, len(categories))
        colordict = dict(zip(categories, colors))  
    
        df["Color"] = df[catcol].apply(lambda x: colordict[x])
        ax.scatter(df[xcol], df[ycol], c=df.Color)
        return fig
    
    if 1:
        df = pd.DataFrame({'Height':np.random.normal(size=10),
                           'Weight':np.random.normal(size=10),
                           'Gender': ["Male","Male","Unknown","Male","Male",
                                      "Female","Did not respond","Unknown","Female","Female"]})    
        fig = dfScatter(df)
        fig.savefig('fig1.png')
    

    这给了我:

    据我所知,该颜色列可以是任何与 matplotlib 兼容的颜色(RBGA 元组、HTML 名称、十六进制值等)。

    我在获取数值以外的任何内容来处理颜色图时遇到了问题。

    【讨论】:

      【解决方案2】:

      您可以使用 plot 方法的 color 参数来定义每列所需的颜色。例如:

      from pandas import DataFrame
      data = DataFrame({'a':range(5),'b':range(1,6),'c':range(2,7)})
      colors = ['yellowgreen','cyan','magenta']
      data.plot(color=colors)
      

      您可以使用颜色名称或颜色十六进制代码,例如“#000000”来表示黑色。您可以在 matplotlib 的 color.py 文件中找到所有定义的颜色名称。下面是 matplotlib 的 github repo 中 color.py 文件的链接。

      https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/colors.py

      【讨论】:

        【解决方案3】:

        其实你可以使用ggplot for python:

        from ggplot import *
        import numpy as np
        import pandas as pd
        
        df = pd.DataFrame({'Height':np.random.randn(10),
                           'Weight':np.random.randn(10),
                           'Gender': ["Male","Male","Male","Male","Male",
                                      "Female","Female","Female","Female","Female"]})
        
        
        ggplot(aes(x='Height', y='Weight', color='Gender'), data=df)  + geom_point()
        

        【讨论】:

          【解决方案4】:

          https://seaborn.pydata.org/generated/seaborn.scatterplot.html

          import numpy 
          import pandas
          import seaborn as sns
          
          numpy.random.seed(0)
          N = 37
          _genders= ['Female', 'Male', 'Non-binary', 'No Response']
          df = pandas.DataFrame({
              'Height (cm)': numpy.random.uniform(low=130, high=200, size=N),
              'Weight (kg)': numpy.random.uniform(low=30, high=100, size=N),
              'Gender': numpy.random.choice(_genders, size=N)
          })
          
          sns.scatterplot(data=df, x='Height (cm)', y='Weight (kg)', hue='Gender')
          

          【讨论】:

            【解决方案5】:
            • 添加此答案是因为该问题是规范的,并且许多用户正在寻求分类或数字数据的答案。
              • OP 按分类列着色,但此答案适用于按 numeric 或可以解释为数字的列着色,例如 datetime dtype强>。
            • pandas.DataFrame.plotmatplotlib.pyplot.scatter 可以采用 ccolor 参数,该参数必须是颜色、颜色序列或数字序列。
            • python 3.8pandas 1.3.1matplotlib 3.4.2 中测试
            • Choosing Colormaps in Matplotlib 用于其他有效的cmap 选项。

            导入和测试数据

            • 'Date' 已经是来自DataReaderdatetime64[ns] dtype
            • conda install -c anaconda pandas-datareaderpip install pandas-datareader 取决于您的环境。
            import pandas as pd
            import matplotlib.pyplot as plt
            import pandas_datareader as web  # for data; not part of pandas
            
            tickers = 'amzn'
            df = web.DataReader(ticker, data_source='yahoo', start='2018-01-01', end='2021-01-01').reset_index()
            df['ticker'] = ticker
            
                    Date        High          Low         Open        Close   Volume    Adj Close ticker
            0 2018-01-02  1190.00000  1170.510010  1172.000000  1189.010010  2694500  1189.010010   amzn
            1 2018-01-03  1205.48999  1188.300049  1188.300049  1204.199951  3108800  1204.199951   amzn
            

            c 作为数字

            pandas.DataFrame.plot

            • df.Date.dt.month 创建一个包含月份数的 pandas.Series
            ax = df.plot(kind='scatter', x='Date', y='High', c=df.Date.dt.month, cmap='Set3', figsize=(11, 4), title='c parameter as a month number')
            plt.show()
            

            matplotlib.pyplot.scatter

            fig, ax = plt.subplots(figsize=(11, 4))
            ax.scatter(data=df, x='Date', y='High', c=df.Date.dt.month, cmap='Set3')
            ax.set(title='c parameter as a month number', xlabel='Date', ylabel='High')
            plt.show()
            

            c 作为datetime dtype

            pandas.DataFrame.plot

            ax = df.plot(kind='scatter', x='Date', y='High', c='Date', cmap='winter', figsize=(11, 4), title='c parameter as a datetime dtype')
            plt.show()
            

            matplotlib.pyplot.scatter

            fig, ax = plt.subplots(figsize=(11, 4))
            ax.scatter(data=df, x='Date', y='High', c='Date', cmap='winter')
            ax.set(title='c parameter as a datetime dtype', xlabel='Date', ylabel='High')
            plt.show()
            

            【讨论】:

              【解决方案6】:

              虽然不是 matplotlib,但您可以使用 plotly express 实现此目的:

              import numpy as np
              import pandas as pd
              import plotly.express as px
              
              df = pd.DataFrame({
                  'Height':np.random.normal(size=10),
                  'Weight':np.random.normal(size=10),
                  'Size': 1,  # How large each point should be?
                  'Gender': ["Male","Male","Male","Male","Male","Female","Female","Female","Female","Female"]})
              
              # Create your plot
              px.scatter(df, x='Weight', y='Height', size='Size', color='Gender')
              

              如果在笔记本中创建,您将获得如下交互式输出:

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-12-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-02-28
                相关资源
                最近更新 更多