【问题标题】:Jitter in scatterplot for non-numeric x-axis非数字 x 轴散点图中的抖动
【发布时间】:2021-03-04 15:56:16
【问题描述】:

我正在寻找一种描述性地分散pandas.DataFrame 的方法,类似于:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   type    1000 non-null   object
 1   value   1000 non-null   int64
 2   count   1000 non-null   int64
dtypes: int64(2), object(1)
memory usage: 23.6+ KB

使用pandas.DataFrame.plotseaborn.scatterplot,每个type 的点都放置在一条垂直线上,彼此重叠。为了缓解这个问题,我想在 x 方向上至少引入一些抖动,但我不知道如何。

到目前为止我的情节:

import pandas as pd
import matplotlib.pyplot as plt
import random

df = pd.DataFrame({
    'type': [random.choice(['t1', 't2', 't3']) for _ in range(1000)],
    'value': [random.randint(0, 500) for _ in range(1000)],
    'count': [random.randint(0,250) for _ in range(1000)],
    })

df.plot(kind='scatter', x='type', y='value', c='count', cmap='Blues')
plt.show()

import seaborn as sns

sns.scatterplot(x='type', y='value', data=df, hue='count')
plt.show()

【问题讨论】:

    标签: python dataframe matplotlib seaborn scatter-plot


    【解决方案1】:

    您的方法的问题是 seaborn 的 scatterplot 缺少在分类数据上下文中有意义的特定功能,例如 jitter。因此,seaborn 提供了“分类数据的散点图”:stripplotswarmplot。但是 seaborn 创造了一个……有趣的人物传奇。我们必须摆脱它并用颜色条替换它:

    #fake data generation
    import pandas as pd
    import numpy as np
    
    np.random.seed(123)
    ndf = 1000
    df = pd.DataFrame({
        'Type': [np.random.choice(['t1', 't2', 't3']) for _ in range(ndf)],
        'Val': [np.random.randint(0, 700) for _ in range(ndf)],
        'Cou': [np.random.randint(0, 500) for _ in range(ndf)],
        })
        
    #now the actual plotting  
    import seaborn as sns
    from matplotlib import colors, cm
    import matplotlib.pyplot as plt
        
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
    
    #preparation for the colorbars
    pal = "coolwarm"
    normpal = colors.Normalize(df.Cou.min(), df.Cou.max())
    
    #stripplot display
    sns.stripplot(x="Type", y="Val", data=df, hue="Cou", palette=pal, ax=ax1, jitter=0.2)
    ax1.get_legend().remove()
    ax1.set_title("stripplot")
    fig.colorbar(cm.ScalarMappable(cmap=pal, norm=normpal), ax=ax1)
    
    #swarmplot display
    sns.swarmplot(x="Type", y="Val", data=df, hue="Cou", palette=pal, ax=ax2)
    ax2.get_legend().remove()
    ax2.set_title("swarmplot")
    fig.colorbar(cm.ScalarMappable(cmap=pal, norm=normpal), ax=ax2)
    
    plt.tight_layout()
    plt.show()
    

    示例输出:

    【讨论】:

    • > 您的方法的问题在于,根据定义,seaborn 的散点图适用于数值数据。我不会这么说的。 seaborn 中的分类绘图函数明确将所有数据视为分类数据,但反之则不成立; scatterplot(借助 matplotlib 中的分类支持)可以完美地处理分类变量。但它目前确实缺少一些仅或主要在分类数据上下文中有意义的功能(如抖动)。
    • 没什么可补充的。真实的数据。根据您的输入编辑了描述。
    • 正是我想要的。在this answer 的帮助下,我能够标记colorbar (matplotlib.axes.Axes.set_ylabel)。
    【解决方案2】:

    我设法通过用数值编码类型来抖动类型,然后改为抖动它们。但是,这需要在DataFrame 中至少再增加 1 列。

    import pandas as pd
    import matplotlib.pyplot as plt
    import random
    
    df = pd.DataFrame({
        'type': [random.choice(['t1', 't2', 't3']) for _ in range(1000)],
        'value': [random.randint(0, 500) for _ in range(1000)],
        'count': [random.randint(0,250) for _ in range(1000)],
        })
    
    def jitter(x):
        return x + random.uniform(0, .5) -.25
    
    type_ids = {'t1': 1, 't2': 2, 't3': 3}
    
    df['type_id'] = df['type'].apply(lambda x: type_ids[x])
    df['jitter_type'] = df['type_id'].apply(lambda x: jitter(x))
    
    df.plot(kind='scatter', x='jitter_type', y='value', c='count', cmap='Blues')
    plt.xticks([1,2,3])
    plt.gca().set_xticklabels(['t1', 't2', 't3'])
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 2021-09-07
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-24
      • 1970-01-01
      • 2019-07-07
      相关资源
      最近更新 更多