【问题标题】:Pandas groupby scatter plot in a single plot单个图中的 Pandas groupby 散点图
【发布时间】:2019-10-17 01:14:08
【问题描述】:

这是来自solution 的后续问题。 kind=line 时会自动分配不同的颜色,但对于散点图则不然。

import pandas as pd
import matplotlib.pylab as plt
import numpy as np

# random df
df = pd.DataFrame(np.random.randint(0,10,size=(25, 3)), columns=['label','x','y'])

# plot groupby results on the same canvas 
fig, ax = plt.subplots(figsize=(8,6))
df.groupby('label').plot(kind='scatter', x = "x", y = "y", ax=ax)

有一个相关问题here。有什么简单的解决方法吗?

更新:

当我尝试@ImportanceOfBeingErnest 为带有字符串的label 列推荐的解决方案时,它不起作用!

df = pd.DataFrame(np.random.randint(0,10,size=(5, 2)), columns=['x','y'])
df['label'] = ['yes','no','yes','yes','no']
fig, ax = plt.subplots(figsize=(8,6))
ax.scatter(x='x', y='y', c='label', data=df) 

它会引发以下错误,

ValueError:无效的 RGBA 参数:“是”

在处理上述异常的过程中,又发生了一个异常:

【问题讨论】:

  • 你仅限于 matplotlib 吗?如果不尝试查看seaborn,它是 mpl 的包装器并减少了样板代码(并且 DataFrames 是一等公民)
  • ax.scatter(x = "Xcoord", y = "Ycoord", c='ProjID', data=df) 呢?
  • 似乎有效,谢谢!但是为什么pd.groupby.plot() 对此不起作用?有什么解决办法吗?
  • @ImportanceOfBeingErnest,如果“标签”列是字符串,那么推荐的解决方案不起作用
  • 是的,matplotlib 不理解“分类”颜色。当然还有其他选择,比如创建一个新列,其中字符串映射到数字,或者循环 df.groupby 并创建单独的散点图

标签: python pandas matplotlib


【解决方案1】:

如果我们已经有分组数据,那么我发现以下解决方案可能很有用。

df = pd.DataFrame(np.random.randint(0,10,size=(5, 2)), columns=['x','y'])
df['label'] = ['yes','no','yes','yes','no']
fig, ax = plt.subplots(figsize=(7,3))


def plot_grouped_df(grouped_df,
                    ax,  x='x', y='y', cmap = plt.cm.autumn_r):

    colors = cmap(np.linspace(0.5, 1, len(grouped_df)))

    for i, (name,group) in enumerate(grouped_df):
        group.plot(ax=ax,
                   kind='scatter', 
                   x=x, y=y,
                   color=colors[i],
                   label = name)

# now we can use this function to plot the groupby data with categorical values
plot_grouped_df(df.groupby('label'),ax)

【讨论】:

    【解决方案2】:

    您可以循环遍历groupby 并为每个组创建一个散点图。这对于不到 10 个类别是有效的。

    import pandas as pd
    import matplotlib.pylab as plt
    import numpy as np
    
    # random df
    df = pd.DataFrame(np.random.randint(0,10,size=(5, 2)), columns=['x','y'])
    df['label'] = ['yes','no','yes','yes','no']
    
    # plot groupby results on the same canvas 
    fig, ax = plt.subplots(figsize=(8,6))
    
    for n, grp in df.groupby('label'):
        ax.scatter(x = "x", y = "y", data=grp, label=n)
    ax.legend(title="Label")
    
    plt.show()
    

    或者,您可以创建一个像这样的散点图

    import pandas as pd
    import matplotlib.pylab as plt
    import numpy as np
    
    # random df
    df = pd.DataFrame(np.random.randint(0,10,size=(5, 2)), columns=['x','y'])
    df['label'] = ['yes','no','yes','yes','no']
    
    # plot groupby results on the same canvas 
    fig, ax = plt.subplots(figsize=(8,6))
    
    u, df["label_num"] = np.unique(df["label"], return_inverse=True)
    
    sc = ax.scatter(x = "x", y = "y", c = "label_num", data=df)
    ax.legend(sc.legend_elements()[0], u, title="Label")
    
    plt.show()
    

    【讨论】:

    • 当我尝试你的第二个解决方案时,它给出了`AttributeError: 'PathCollection' object has no attribute 'legend_elements'`这个错误,你能检查一下吗?
    • 是的,legend_elements 是一个函数 I introduced 只是最近。为此,您需要 matplotlib 3.1。
    • 哦。伟大的 !!!我会升级我的。非常感谢您对开源工具的贡献 :)
    【解决方案3】:

    IIUC 您可以为此使用sns:

    df = pd.DataFrame(np.random.randint(0,10,size=(100, 2)), columns=['x','y'])
    df['label'] = np.random.choice(['yes','no','yes','yes','no'], 100)
    fig, ax = plt.subplots(figsize=(8,6))
    sns.scatterplot(x='x', y='y', hue='label', data=df) 
    plt.show()
    

    输出:

    另一个选项是评论中建议的:将值映射到数字,按分类类型:

    fig, ax = plt.subplots(figsize=(8,6))
    ax.scatter(df.x, df.y, c = pd.Categorical(df.label).codes, cmap='tab20b')
    plt.show()
    

    输出:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-18
      • 1970-01-01
      • 2019-03-28
      • 1970-01-01
      • 2017-08-21
      • 1970-01-01
      • 1970-01-01
      • 2014-09-06
      相关资源
      最近更新 更多