绘制具有多个属性的图形,类似于 Seaborn 中的“色调”

Posted

技术标签:

【中文标题】绘制具有多个属性的图形,类似于 Seaborn 中的“色调”【英文标题】:Plot graph with multiple attributes similar to "hue" in Seaborn 【发布时间】:2018-11-09 16:36:20 【问题描述】:

我有以下名为df 的示例数据集,其中阶段时间是到达那里的天数:

id stage1_time stage_1_to_2_time stage_2_time stage_2_to_3_time stage3_time
a  10          30                40           30                70
b  30               
c  15          30                45     
d       

我编写了以下脚本以获得stage1_time 与 CDF 的散点图:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats

dict = 'id': id, 'stage_1_time': [10, 30, 15, None], 'stage_1_to_2_time': [30, None, 30, None], 'stage_2_time' : [40, None, 45, None],'stage_2_to_3_time' : [30, None, None, None],'stage_3_time' : [70, None, None, None]
df = pd.DataFrame(dict)

#create eCDF function
def ecdf(df):
    n = len(df)
    x = np.sort(df)
    y = np.arange(1.0, n+1) / n
    return x, y

def generate_scatter_plot(df):

    x, y = ecdf(df)

    plt.plot(x, y, marker='.', linestyle='none') 
    plt.axvline(x.mean(), color='gray', linestyle='dashed', linewidth=2) #Add mean

    x_m = int(x.mean())
    y_m = stats.percentileofscore(df.as_matrix(), x.mean())/100.0

    plt.annotate('(%s,%s)' % (x_m,int(y_m*100)) , xy=(x_m,y_m), xytext=(10,-5), textcoords='offset points')

    percentiles= np.array([0,25,50,75,100])
    x_p = np.percentile(df, percentiles)
    y_p = percentiles/100.0

    plt.plot(x_p, y_p, marker='D', color='red', linestyle='none') # Overlay quartiles

    for x,y in zip(x_p, y_p):                                        
        plt.annotate('%s' % int(x), xy=(x,y), xytext=(10,-5), textcoords='offset points')

#Data to plot
stage1_time = df['stage_1_time'].dropna().sort_values()

#Scatter Plot
stage1_time_scatter = generate_scatter_plot(pd.DataFrame("df" : stage1_time.as_matrix()))
plt.title('Scatter Plot of Days to Stage1')
plt.xlabel('Days to Stage1')
plt.ylabel('Cumulative Probability')
plt.legend(('Days to Stage1', "Mean", 'Quartiles'), loc='lower right')
plt.margins(0.02)

plt.show()

输出:

目前,我将所有到达stage1 的人与其累积概率绘制成图的天数,但是我想要实现的是,当我绘制时,散点具有三种颜色:那些到达stage1 并留在那里的人,那些转移到stage2的人,以及那些转移到stage3的人。我还想要图中数据的计数:#in stage1,#in stage2 和#in stage3

有人可以帮忙吗?

仅供参考,打算以此为基础,以便我还可以为stage2_time 创建一个图表,其中到达stage_3 的人以不同的颜色突出显示。

【问题讨论】:

【参考方案1】:

您可以创建一个新列并使用它来存储最终阶段,然后使用这个新列为您的绘图着色。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats
import math

dict = 'id': id, 'Progressive_time': [10, 30, 15, None],'stage_1_to_2_time': [30, None, 30, None], 'Active_time' : [40,None, 45, None],'stage_2_to_3_time' : [30, None, None,None],'Engaged_time' : [70, None, None, None]
df = pd.DataFrame(dict)

    #create eCDF function
def ecdf(df, serie):
    n = len(df)
    df['x'] = np.sort(df[serie])
    df['y'] = np.arange(1.0, n+1) / n
    return df

def generate_scatter_plot(df,serie,nb_stage):
    df=df.dropna(subset=[serie]).sort_values(by=[serie])
    st=1
    for i in range(1,nb_stage*2,2):
        df.loc[df.iloc[:,i].notnull(),'stage']=st
        st=st+1

    df= ecdf(df, serie)
    plt.plot(df.loc[df['stage'] == 1, 'x'], df.loc[df['stage'] == 1, 'y'], marker='.', linestyle='none',c='blue') 
    plt.plot(df.loc[df['stage'] == 2, 'x'], df.loc[df['stage'] == 2, 'y'], marker='.', linestyle='none',c='red') 
    plt.plot(df.loc[df['stage'] == 3, 'x'], df.loc[df['stage'] == 3, 'y'], marker='.', linestyle='none',c='green') 
    plt.axvline(df['x'].mean(), color='gray', linestyle='dashed', linewidth=2) #Add mean


    x_m = int(df['x'].mean())
    y_m = stats.percentileofscore(df[serie], df['x'].mean())/100.0

    plt.annotate('(%s,%s)' % (x_m,int(y_m*100)) , xy=(x_m,y_m), xytext=(10,-5), textcoords='offset points')

    percentiles= np.array([0,25,50,75,100])
    x_p = np.percentile(df[serie], percentiles)
    y_p = percentiles/100.0

    plt.plot(x_p, y_p, marker='D', color='red', linestyle='none') # Overlay quartiles

    for x,y in zip(x_p, y_p):                                        
        plt.annotate('%s' % int(x), xy=(x,y), xytext=(10,-5), textcoords='offset points')

#Scatter Plot
stage1_time_scatter = generate_scatter_plot(df,'stage_1_time',3)
plt.title('Scatter Plot of Days to Stage1')
plt.xlabel('Days to Stage1')
plt.ylabel('Cumulative Probability')
plt.legend(('Progressive','Active','Engaged','Days to Stage1', "Mean", 'Quartiles'), loc='lower right')
plt.margins(0.02)

plt.show()

【讨论】:

谢谢你这是完美的!问题,关于def generate_scatter_plot- 有没有办法从定义本身中取出硬编码的stage_3_timestage_2_time?我也希望能够将它更广泛地用于其他情况? 我编辑了我的代码。现在在generate_scatter_plot 中,您可以设置多个阶段。对于情节图例,您可以在generate_scatter_plot 中编辑或添加列表 谢谢!两个问题:1)我称阶段 1、2、3 但实际上它们是字母定义(如 Progressive、Active、Engaged)——我还能按原样使用代码吗? 2)如果我需要,它是否足够通用,可用于那些收到特定电子邮件的人(例如,这将是一个不同的系列,即 df 中的列),而不是那些继续进入第 2 阶段和第 3 阶段的人? 数据框的列必须使用相同的结构,但名称并不重要 谢谢你,这真的很棒!查看聊天中的问题chat.***.com/rooms/172432/…

以上是关于绘制具有多个属性的图形,类似于 Seaborn 中的“色调”的主要内容,如果未能解决你的问题,请参考以下文章

Seaborn/Plotly 多个 y 轴

停止 seaborn 在彼此之上绘制多个图形

如何在seaborn中将多个图形绘制为数据框的子图和多列?

在相同的绘图空间上绘制两个 Seaborn sns.kdeplot 图形,但每个图形都有一个具有相同范围的不同颜色条

如何缩放具有不同频率的多个KDE图?

具有多个系列的 Seaborn 时间序列图