精华内容
下载资源
问答
  • seaborn

    2020-02-17 20:50:30
    1.1 Seaborn----绘制统计图形 Matplotlib虽然已经是比较优秀的绘图库了,但是它有个今人头疼的问题,那就是API使用过于复杂,它里面有上千个函数和参数,属于典型的那种可以用它做任何事,却无从下手。 Seaborn...

    日萌社

    人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


    1.1 Seaborn----绘制统计图形

    Matplotlib虽然已经是比较优秀的绘图库了,但是它有个今人头疼的问题,那就是API使用过于复杂,它里面有上千个函数和参数,属于典型的那种可以用它做任何事,却无从下手。

    Seaborn基于 Matplotlib核心库进行了更高级的API封装,可以轻松地画出更漂亮的图形,而Seaborn的漂亮主要体现在配色更加舒服,以及图形元素的样式更加细腻。

    不过,使用Seaborn绘制图表之前,需要安装和导入绘图的接口,具体代码如下:

    # 安装 
    pip3 install seaborn
    
    # 导入
    import seaborn as sns
    

    接下来,我们正式进入 Seaborn库的学习

    1 可视化数据的分布

    当处理一组数据时,通常先要做的就是了解变量是如何分布的。

    • 对于单变量的数据来说 采用直方图或核密度曲线是个不错的选择,
    • 对于双变量来说,可采用多面板图形展现,比如 散点图、二维直方图、核密度估计图形等。

    针对这种情况, Seaborn库提供了对单变量和双变 量分布的绘制函数,如 displot()函数、 jointplot()函数,下面来介绍这些函数的使用,具体内容如下:

    2 绘制单变量分布

    可以采用最简单的直方图描述单变量的分布情况。 Seaborn中提供了 distplot()函数,它默认绘制的是一个带有核密度估计曲线的直方图。 distplot()函数的语法格式如下。

    seaborn.distplot(a, bins=None, hist=True, kde=True, rug=False, fit=None, color=None)
    

    上述函数中常用参数的含义如下:

    • (1) a:表示要观察的数据,可以是 Series、一维数组或列表。

    • (2) bins:用于控制条形的数量。

    • (3) hist:接收布尔类型,表示是否绘制(标注)直方图。

    • (4) kde:接收布尔类型,表示是否绘制高斯核密度估计曲线。

    • (5) rug:接收布尔类型,表示是否在支持的轴方向上绘制rugplot。

    通过 distplot())函数绘制直方图的示例如下。

    import numpy as np
    
    sns.set()
    np.random.seed(0)  # 确定随机数生成器的种子,如果不使用每次生成图形不一样
    arr = np.random.randn(100)  # 生成随机数组
    
    ax = sns.distplot(arr, bins=10, hist=True, kde=True, rug=True)  # 绘制直方图
    

    上述示例中,首先导入了用于生成数组的numpy库,然后使用 seaborn调用set()函数获取默认绘图,并且调用 random模块的seed函数确定随机数生成器的种子,保证每次产生的随机数是一样的,接着调用 randn()函数生成包含100个随机数的数组,最后调用 distplot()函数绘制直方图。

    运行结果如下图所示。

    从上图中看出:

    • 直方图共有10个条柱,每个条柱的颜色为蓝色,并且有核密度估计曲线。
    • 根据条柱的高度可知,位于-1-1区间的随机数值偏多,小于-2的随机数值偏少。

    通常,采用直方图可以比较直观地展现样本数据的分布情况,不过,直方图存在一些问题,它会因为条柱数量的不同导致直方图的效果有很大的差异。为了解决这个问题,可以绘制核密度估计曲线进行展现。

    • 核密度估计是在概率论中用来估计未知的密度函数,属于非参数检验方法之一,可以比较直观地看出数据样本本身的分布特征。

    通过 distplot()函数绘制核密度估计曲线的示例如下。

    # 创建包含500个位于[0,100]之间整数的随机数组
    array_random = np.random.randint(0, 100, 500)
    # 绘制核密度估计曲线
    sns.distplot(array_random, hist=False, rug=True)
    

    上述示例中,首先通过 random.randint()函数返回一个最小值不低于0、最大值低于100的500个随机整数数组然后调用 displot()函数绘制核密度估计曲线。

    运行结果如图所示。

    从上图中看出,图表中有一条核密度估计曲线,并且在x轴的上方生成了观测数值的小细条。

    3 绘制双变量分布

    两个变量的二元分布可视化也很有用。在 Seaborn中最简单的方法是使用 jointplot()函数,该函数可以创建一个多面板图形,比如散点图、二维直方图、核密度估计等,以显示两个变量之间的双变量关系及每个变量在单坐标轴上的单变量分布。

    jointplot()函数的语法格式如下。

    seaborn.jointplot(x, y, data=None, 
                      kind='scatter', stat_func=None, color=None, 
                      ratio=5, space=0.2, dropna=True)
    

    上述函数中常用参数的含义如下:

    • (1) kind:表示绘制图形的类型。
    • (2) stat_func:用于计算有关关系的统计量并标注图。
    • (3) color:表示绘图元素的颜色。
    • (4) size:用于设置图的大小(正方形)。
    • (5) ratio:表示中心图与侧边图的比例。该参数的值越大,则中心图的占比会越大。
    • (6) space:用于设置中心图与侧边图的间隔大小。

    下面以散点图、二维直方图、核密度估计曲线为例,为大家介绍如何使用 Seaborn绘制这些图形。

    3.1 绘制散点图

    调用 seaborn.jointplot()函数绘制散点图的示例如下。

    import numpy as np
    import pandas as pd
    import seaborn as sns
    
    # 创建DataFrame对象
    dataframe_obj = pd.DataFrame({"x": np.random.randn(500),"y": np.random.randn(500)})
    # 绘制散布图
    sns.jointplot(x="x", y="y", data=dataframe_obj)
    

    上述示例中,首先创建了一个 DataFrame对象 dataframe_obj作为散点图的数据,其中x轴和y轴的数据均为500个随机数,接着调用 jointplot0函数绘制一个散点图,散点图x轴的名称为“x”,y轴的名称为“y”。

    运行结果如图所示。

    3.2 绘制二维直方图

    二维直方图类似于“六边形”图,主要是因为它显示了落在六角形区域内的观察值的计数,适用于较大的数据集。当调用 jointplot()函数时,只要传入kind="hex",就可以绘制二维直方图,具体示例代码如下。

    # 绘制二维直方图
    sns.jointplot(x="x", y="y", data=dataframe_obj, kind="hex")
    

    运行结果如图所示。

    从六边形颜色的深浅,可以观察到数据密集的程度,另外,图形的上方和右侧仍然给出了直方图。注意,在绘制二维直方图时,最好使用白色背景。

    3.3 绘制核密度估计图形

    利用核密度估计同样可以查看二元分布,其用等高线图来表示。当调用jointplot()函数时只要传入ind="kde",就可以绘制核密度估计图形,具体示例代码如下。

    sns.jointplot(x="x", y="y", data=dataframe_obj, kind="kde")
    

    上述示例中,绘制了核密度的等高线图,另外,在图形的上方和右侧给出了核密度曲线图。

    运行结果如图所示。

    通过观等高线的颜色深浅,可以看出哪个范围的数值分布的最多,哪个范围的数值分布的最少

    4 绘制成对的双变量分布

    要想在数据集中绘制多个成对的双变量分布,则可以使用pairplot()函数实现,该函数会创建一个坐标轴矩阵,并且显示Datafram对象中每对变量的关系。另外,pairplot()函数也可以绘制每个变量在对角轴上的单变量分布。

    接下来,通过 sns.pairplot()函数绘制数据集变量间关系的图形,示例代码如下

    # 加载seaborn中的数据集
    dataset = sns.load_dataset("iris")
    
    dataset.head()
    

    上述示例中,通过 load_dataset0函数加载了seaborn中内置的数据集,根据iris数据集绘制多个双变量分布。

    # 绘制多个成对的双变量分布
    sns.pairplot(dataset)
    

    结果如下图所示。

    5 小结

    • seaborn的基本使用【了解】
    • 绘制单变量分布图形【知道】
      • seaborn.distplot()
    • 绘制双变量分布图形【知道】
      • seaborn.jointplot()
    • 绘制成对的双变量分布图形【知道】
      • Seaborn.pairplot()

    import seaborn as sns
    import numpy as np
    import pandas as pd
    

    绘制单变量分布

    In [13]:

    np.random.seed(0)  # 确定随机数生成器生成的数据是一样的
    
    arr = np.random.randn(100)
    
    sns.distplot(arr, bins=10, hist=True, kde=True, rug=True)

     

    绘制双变量分布

    绘制散点图

    In [16]:

    df = pd.DataFrame({"x":np.random.randn(500), "y":np.random.randn(500)})
    

    In [18]:

    df.head()

    sns.jointplot("x", "y", data=df, kind="scatter", stat_func=None, color="r", size=10, ratio=5, space=1)
    

    绘制二维直方图

    In [35]:

    sns.jointplot("x", "y", data=df, kind="hex")

    绘制核密度估计图形

    In [36]:

    sns.jointplot("x", "y", data=df, kind="kde")

    绘制成对的双变量分布

    In [37]:

    dataset = sns.load_dataset("iris")
    
    dataset.head()

    sns.pairplot(dataset)
    

    类别散点图

    In [41]:

    data = sns.load_dataset("tips")
    

    In [42]:

    data.head()

    sns.stripplot(x="day", y="total_bill", data=data, hue="time")
    

    sns.stripplot(x="day", y="total_bill", data=data, hue="time", jitter=True)
    

    sns.swarmplot("day", "total_bill", data=data)
    

    类别内数据分布

    箱型图

    In [57]:

    sns.boxplot("day", "total_bill", data=data, hue="time", palette=["g", "r"], saturation=0.9)

    绘制提琴图

    In [58]:

    sns.violinplot("day", "total_bill", data=data)

    类别内的估计统计

    In [59]:

    sns.barplot("day", "total_bill", data=data)

    sns.pointplot("day", "total_bill", data=data)
    


    1.2 用分类数据绘图

    数据集中的数据类型有很多种,除了连续的特征变量之外,最常见的就是类别型的数据了,比如人的性别、学历、爱好等,这些数据类型都不能用连续的变量来表示,而是用分类的数据来表示。

    Seaborn针对分类数据提供了专门的可视化函数,这些函数大致可以分为如下三种:

    • 分类数据散点图: swarmplot()与 stripplot()。
    • 类数据的分布图: boxplot() 与 violinplot()。
    • 分类数据的统计估算图:barplot() 与 pointplot()。

    下面两节将针对分类数据可绘制的图形进行简单介绍,具体内容如下

    1 类别散点图

    通过 stripplot()函数可以画一个散点图, stripplot0函数的语法格式如下。

    seaborn.stripplot(x=None, y=None, hue=None, data=None, order=None, hue_order=None, jitter=False)
    

    上述函数中常用参数的含义如下

    • (1) x,y,hue:用于绘制长格式数据的输入。
    • (2) data:用于绘制的数据集。如果x和y不存在,则它将作为宽格式,否则将作为长格式。
    • (3) jitter:表示抖动的程度(仅沿类別轴)。当很多数据点重叠时,可以指定抖动的数量或者设为Tue使用默认值。

    为了让大家更好地理解,接下来,通过 stripplot()函数绘制一个散点图,示例代码如下。

    # 获取tips数据
    tips = sns.load_dataset("tips")
    
    sns.stripplot(x="day", y="total_bill", data=tips)
    

    运行结果如下图所示。

    从上图中可以看出,图表中的横坐标是分类的数据,而且一些数据点会互相重叠,不易于观察。为了解决这个问题,可以在调用striplot()函数时传入jitter参数,以调整横坐标的位置,改后的示例代码如下。

    sns.stripplot(x="day", y="total_bill", data=tips, jitter=True)
    

    运行结果如下图所示。

    除此之外,还可调用 swarmplot0函数绘制散点图,该函数的好处是所有的数据点都不会重叠,可以很清晰地观察到数据的分布情况,示例代码如下。

    sns.swarmplot(x="day", y="total_bill", data=tips)
    

    运行结果如图所示。

    2 类别内的数据分布

    要想查看各个分类中的数据分布,显而易见,散点图是不满足需求的,原因是它不够直观。针对这种情况,我们可以绘制如下两种图形进行查看:

    • 箱形图:
      • 箱形图(Box-plot)又称为盒须图、盒式图或箱线图,是一种用作显示一组数据分散情况资料的统计图。因形状如箱子而得名。
      • 箱形图于1977年由美国著名统计学家约翰·图基(John Tukey)发明。它能显示出一组数据的最大值、最小值、中位数、及上下四分位数。

    小提琴图:

    • 小提琴图 (Violin Plot) 用于显示数据分布及其概率密度。
    • 这种图表结合了箱形图和密度图的特征,主要用来显示数据的分布形状。
    • 中间的黑色粗条表示四分位数范围,从其延伸的幼细黑线代表 95% 置信区间,而白点则为中位数。
    • 箱形图在数据显示方面受到限制,简单的设计往往隐藏了有关数据分布的重要细节。例如使用箱形图时,我们不能了解数据分布。虽然小提琴图可以显示更多详情,但它们也可能包含较多干扰信息。

    接下来,针对 Seaborn库中箱形图和提琴图的绘制进行简单的介绍。

    2.1 绘制箱形图

    seaborn中用于绘制箱形图的函数为 boxplot(),其语法格式如下:

    seaborn.boxplot(x=None, y=None, hue=None, data=None, orient=None, color=None,  saturation=0.75, width=0.8)
    

    常用参数的含义如下:

    • (1) palette:用于设置不同级别色相的颜色变量。---- palette=["r","g","b","y"]
    • (2) saturation:用于设置数据显示的颜色饱和度。---- 使用小数表示

    使用 boxplot()函数绘制箱形图的具体示例如下。

    sns.boxplot(x="day", y="total_bill", data=tips)
    

    上述示例中,使用 seaborn中内置的数据集tips绘制了一个箱形图,图中x轴的名称为day,其刻度范围是 Thur~Sun(周四至周日),y轴的名称为 total_bill,刻度范围为10-50左右

    运行结果如图所示。

    从图中可以看出,

    • Thur列大部分数据都小于30,不过有5个大于30的异常值,
    • Fri列中大部分数据都小于30,只有一个异常值大于40,
    • Sat一列中有3个大于40的异常值,
    • Sun列中有两个大于40的异常值

    2.2 绘制提琴图

    seaborn中用于绘制提琴图的函数为violinplot(),其语法格式如下

    seaborn.violinplot(x=None, y=None, hue=None, data=None)
    

    通过violinplot()函数绘制提琴图的示例代码如下

    sns.violinplot(x="day", y="total_bill", data=tips)
    

    上述示例中,使用seaborn中内置的数据集绘制了一个提琴图,图中x轴的名称为day,y轴的名称为total_bill

    运行结果如图所示。

    从图中可以看出,

    • Thur一列中位于5~25之间的数值较多,
    • Fri列中位于5-30之间的较多,
    • Sat-列中位于5-35之间的数值较多,
    • Sun一列中位于5-40之间的数值较多。

    3 类别内的统计估计

    要想查看每个分类的集中趋势,则可以使用条形图和点图进行展示。 Seaborn库中用于绘制这两种图表的具体函数如下

    • barplot()函数:绘制条形图。
    • pointplot()函数:绘制点图。

    这些函数的API与上面那些函数都是一样的,这里只讲解函数的应用,不再过多对函数的语法进行讲解了。

    3.1 绘制条形图

    最常用的查看集中趋势的图形就是条形图。默认情况下, barplot函数会在整个数据集上使用均值进行估计。若每个类别中有多个类别时(使用了hue参数),则条形图可以使用引导来计算估计的置信区间(是指由样本统计量所构造的总体参数的估计区间),并使用误差条来表示置信区间。

    使用 barplot()函数的示例如下

    sns.barplot(x="day", y="total_bill", data=tips)
    

    运行结果如图所示。

    3.2 绘制点图

    另外一种用于估计的图形是点图,可以调用 pointplot()函数进行绘制,该函数会用高度低计值对数据进行描述,而不是显示完整的条形,它只会绘制点估计和置信区间

    通过 pointplot()函数绘制点图的示例如下。

    sns.pointplot(x="day", y="total_bill", data=tips)
    

    运行结果如图所示。

    4 小结

    • 类别散点图
      • seaborn.stripplot()
    • 类别内的数据分布
      • 箱线图
        • seaborn.boxplot()
      • 小提琴图
        • seaborn.violinplot()
    • 类别内的统计估计
      • 条形图
        • barplot()
      • 点图
        • pointplot()

    1.3 案例:NBA球员数据分析

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns

    获取数据

    In [2]:

    data = pd.read_csv("./data/nba_2017_nba_players_with_salary.csv")
    

    In [3]:

    data.head()

    data.shape
    

    Out[4]:

    (342, 38)

    In [5]:

    data.describe()

    数据分析

    数据相关性

    In [7]:

    data_cor = data.loc[:, ['RPM', 'AGE', 'SALARY_MILLIONS', 'ORB', 'DRB', 'TRB',
                           'AST', 'STL', 'BLK', 'TOV', 'PF', 'POINTS', 'GP', 'MPG', 'ORPM', 'DRPM']]
    
    data_cor.head()

    corr = data_cor.corr()
    

    In [10]:

    # 获取两列数据之间的相关性
    corr.head()

    plt.figure(figsize=(20, 8), dpi=100)
    
    sns.heatmap(corr, square=True, linewidths=0.1, annot=True)

    基本数据排名分析

    In [19]:

    # 按照效率值排名
    
    data.loc[:, ["PLAYER", "RPM", "AGE"]].sort_values(by="RPM", ascending=False).head()

    # 按照球员薪资排名
    
    data.loc[:, ["PLAYER", "RPM", "AGE", "SALARY_MILLIONS"]].sort_values(by="SALARY_MILLIONS", ascending=False).head()

    Seaborn常用的三个数据可视化方法

    单变量:

    In [24]:

    # 利用seaborn中的distplot绘图来分别看一下球员薪水、效率值、年龄这三个信息的分布情况
    
    sns.set_style("darkgrid")
    
    plt.figure(figsize=(10, 10))
    
    plt.subplot(3, 1, 1)
    sns.distplot(data["SALARY_MILLIONS"])
    plt.ylabel("salary")
    
    plt.subplot(3, 1, 2)
    sns.distplot(data["RPM"])
    plt.ylabel("RPM")
    
    plt.subplot(3, 1, 3)
    sns.distplot(data["AGE"])
    plt.ylabel("AGE")

    双变量

    In [26]:

    sns.jointplot(data.AGE, data.SALARY_MILLIONS, kind="hex")

    多变量

    In [27]:

    multi_data = data.loc[:, ['RPM','SALARY_MILLIONS','AGE','POINTS']]
    multi_data.head()

     

    sns.pairplot(multi_data)
    

    衍生变量的一些可视化实践-以年龄为例

    In [29]:

    def age_cut(df):
        """年龄划分"""
        if df.AGE <= 24:
            return "young"
        elif df.AGE >= 30:
            return "old"
        else:
            return "best"
    

    In [30]:

    # 使用apply对年龄进行划分
    data["age_cut"] = data.apply(lambda x:age_cut(x), axis=1)
    

    In [31]:

    data.head()

    # 方便计数
    data["cut"] = 1
    

    In [36]:

    data.loc[data.age_cut == "best"].SALARY_MILLIONS.head()

    # 基于年龄段对球员薪水和效率值进行分析
    sns.set_style("darkgrid")
    plt.figure(figsize=(10,10), dpi=100)
    plt.title("RPM and Salary")
    
    x1 = data.loc[data.age_cut == "old"].SALARY_MILLIONS
    y1 = data.loc[data.age_cut == "old"].RPM
    plt.plot(x1, y1, "^")
    
    x2 = data.loc[data.age_cut == "best"].SALARY_MILLIONS
    y2 = data.loc[data.age_cut == "best"].RPM
    plt.plot(x2, y2, "^")
    
    x3 = data.loc[data.age_cut == "young"].SALARY_MILLIONS
    y3 = data.loc[data.age_cut == "young"].RPM
    plt.plot(x3, y3, ".")

    multi_data2 = data.loc[:, ['RPM','POINTS','TRB','AST','STL','BLK','age_cut']]
    
    sns.pairplot(multi_data2, hue="age_cut")

    球队数据分析

    球队薪资排行

    In [43]:

    data.groupby(by="age_cut").agg({"SALARY_MILLIONS":np.max})

    data_team = data.groupby(by="TEAM").agg({"SALARY_MILLIONS":np.mean})
    
    data_team.sort_values(by="SALARY_MILLIONS", ascending=False).head(10)

    # 按照分球队分年龄段,上榜球员降序排列,如上榜球员数相同,则按效率值降序排列。
    data_rpm = data.groupby(by=["TEAM", "age_cut"]).agg({"SALARY_MILLIONS":np.mean,  "RPM":np.mean, "PLAYER":np.size})
    

    In [51]:

    data_rpm.head()

    data_rpm.sort_values(by=["PLAYER", "RPM"], ascending=False).head()
    

    按照球队综合实力排名

    In [56]:

    data_rpm2 = data.groupby(by=['TEAM'], as_index=False).agg({'SALARY_MILLIONS': np.mean,
                                                              'RPM': np.mean,
                                                              'PLAYER': np.size,
                                                              'POINTS': np.mean,
                                                              'eFG%': np.mean,
                                                              'MPG': np.mean,
                                                              'AGE': np.mean})
    

    In [58]:

    data_rpm2.head()

    data_rpm2.sort_values(by="RPM", ascending=False).head()
    

    利用箱线图和小提琴图进行数据分析

    data.TEAM.isin(['GS', 'CLE', 'SA', 'LAC', 'OKC', 'UTAH', 'CHA', 'TOR', 'NO', 'BOS']).head()
    

    sns.set_style("whitegrid")
    plt.figure(figsize=(20, 10))
    # 获取需要的数据
    data_team2 = data[data.TEAM.isin(['GS', 'CLE', 'SA', 'LAC', 'OKC', 'UTAH', 'CHA', 'TOR', 'NO', 'BOS'])]
    
    # 进行相应的绘图
    plt.subplot(3,1,1)
    sns.boxplot(x="TEAM", y="SALARY_MILLIONS", data = data_team2)
    
    plt.subplot(3,1,2)
    sns.boxplot(x="TEAM", y="AGE", data = data_team2)
    
    plt.subplot(3,1,3)
    sns.boxplot(x="TEAM", y="MPG", data = data_team2)

    data.head()
    

    # 绘制小提琴图
    sns.set_style("whitegrid")
    plt.figure(figsize=(20, 10))
    
    plt.subplot(3,1,1)
    sns.violinplot(x="TEAM", y="3P%", data=data_team2)
    
    plt.subplot(3,1,2)
    sns.violinplot(x="TEAM", y="eFG%", data=data_team2)
    
    plt.subplot(3,1,3)
    sns.violinplot(x="TEAM", y="POINTS", data=data_team2)


    2.1 数据分析实战----北京租房数据统计分析

    近年来随着经济的快速发展,一线城市的资源和就业机会吸引了很多外来人口,使其逐渐成为人口密集的城市之一。据统计,2017年北京市常住外来人口已经达到了2170.7万人,其中绝大多数人是以租房的形式解决居住问题。

    本文将租房网站上北京地区的租房数据作为参考,运用前面所学到的数据分析知识,带领大家一起来分析真实数据,并以图表的形式得到以下统计指标:

    • (1)统计每个区域的房源总数量,并使用热力图分析房源位置分布情况
    • (2)使用条形图分析哪种户型的数量最多、更受欢迎。
    • (3)统计每个区域的平均租金,并结合柱状图和折线图分析各区域的房源数量和租金情况。
    • (4)统计面积区间的市场占有率,并使用饼图绘制各区间所占的比例。

    1 数据基本介绍

    目前网络上有很多的租房平台,比如自如、爱屋吉屋、房天下、链家等,其中,链家是目前市场占有率最高的公司,通过链家平台可以便捷且全面地提供可靠的房源信息。如下图所示:

    通过网络爬虫技术,爬取链家网站中列出的租房信息(爬取结束时间为2018年9月10日),具体包括所属区域、小区名称、房屋、价格、房屋面积、户型。需要说明的是,链家官网上并没有提供平谷、怀柔、密云、延庆等偏远地区的租房数据,所以本案例的分析不会涉及这四个地区。

    将爬到的数据下载到本地,并保存在“链家北京租房数据.csv”文件中,打开该文件后可以看到里面有很多条(本案例爬取的数据共计8224条)信息,具体如下图所示。

    2 数据读取

    准备好数据后,我们便可以使用 Pandas读取保存在CSV文件的数据,并将其转换成DataFrame对象展示,便于后续操作这些数据。

    首先,读取数据:

    import pandas as pd
    import numpy as np
    
    # 读取链家北京租房信息
    file_data = pd.read_csv('./data/链家北京租房数据.csv')
    file_data.head()

    3 数据预处理

    尽管从链家官网上直接爬取下来的数据大部分是比较规整的,但或多或少还是会存在一些问题,不能直接用做数据分析。为此,在使用前需要对这些数据进行一系列的检测与处理,包括处理重复值和缺失值、统一数据类型等,以保证数据具有更高的可用性。

    3.1重复值和空值处理

    预处理的前两步就是检查缺失值和重复值。如果希望检查准备的数据中是否存在重复的数据,则可以通过 Pandas中的 duplicated()方法完成。接下来,通过 duplicated()方法对北京租房数据进行检测,只要有重复的数据就会映射为True,具体代码如下。

    # 重复数据检测
    file_data.duplicated()
    

    由于数据量相对较多,所以在 Jupyter NoteBook工具中有一部分数据会省略显示,但是从输出结果中仍然可以看到有多条返回结果为True的数据,这表明有重复的数据。这里,处理重复数据的方式是将其删除。接下来,使用 drop_duplicates()方法直接删除重复的数据,具体代码如下。

    # 删除重复数据
    file_data = file_data.drop_duplicates()
    

    与上一次输出的行数相比,可以很明显地看到减少了很多条数据,只剩下了5773条数据。

    对数据重复检测完成之后,便可以检测数据中是否存在缺失值,我们可以直接使用 dropna()方法检测并删除缺失的数据,具体代码如下。

    # 删除缺失数据
    file_data = file_data.dropna()
    

    经过缺失数据检测之后,可以发现当前数据的总行数与之前相比没有发生任何变化。因此我们断定准备好的数据中并不存在缺失的数据。

    3.2 数据转换类型

    在这套租房数据中,“面积(m^2m​2​​)”一列的数据里面有中文字符,说明这一列数据都是字符串类型的。为了方便后续对面积数据进行数学运算,所以需要将“面积(m)”一列的数据类型转换为float类型,具体代码如下。

    # 创建一个空数组
    data_new = np.array([])
    # 取出“面积”一列数据,将每个数据末尾的中文字符去除  fild_data.info()
    data = file_data['面积(㎡)'].values
    for i in data:
                  data_new = np.append(data_new, np.array(i[:-2]))
    # 通过astype()方法将str类型转换为float64类型
    data = data_new.astype(np.float64)
    # 用新的数据替换
    file_data.loc[:,'面积(㎡)']= data

    除此之外,在“户型”一列中,大部分数据显示的是“室厅”,只有个别数据显示的是"\房间*卫”(比如索引8219对应的一行)。为了方便后期的使用,需要将“房间"替换成"室",以保证数据的一致性。

    接下来,使用 Pandas的 replace()方法完成替换数据的操作,具体代码如下。

    # 获取“户型”一列数据
    housetype_data = file_data['户型']
    temp_list = []
    # 通过replace()方法进行替换
    for i in housetype_data:
        new_info = i.replace('房间','室')
        temp_list.append(new_info)
    file_data.loc[:,'户型'] = temp_list
    

    通过比较处理前与处理后的数据可以发现,索引为8219的户型数据已经由“4房间2卫”变成“4室2卫”,说明数据替换成功。

    4 图表分析

    数据经过预处理以后,便可以用它们来做分析了,为了能够更加直观地看到数据的变化,这里,我们采用图表的方式来辅助分析。

    4.1房源数量、位置分布分析

    如果希望统计各个区域的房源数量,以及查看这些房屋的分布情况,则需要先获取各个区的房源。为了实现这个需求,可以将整个数据按照“区域”一列进行分组。

    为了能够准确地看到各区域的房源数量,这里只需要展示“区域”与“数量”这两列的数据即可。因此,先创建一个空的 DataFrame对象,然后再将各个区域计算的总数量作为该对象的数据进行展示,具体代码如下。

    # 创建一个DataFrame对象,该对象只有两列数据:区域和数量
    
    new_df = pd.DataFrame({'区域':file_data['区域'].unique(),'数量':[0]*13})

    接下来,通过 Pandas的 groupby()方法将 file data对象按照“区域”一列进行分组,并利用count()方法统计每个分组的数量,具体代码如下。

    # 按“区域”列将file_data进行分组,并统计每个分组的数量
    
    groupy_area = file_data.groupby(by='区域').count()
    new_df['数量'] = groupy_area.values

    通过 sort_values()方法对new_df对象排序,按照从大到小的顺序进行排列,具体代码如下。

    # 按“数量”一列从大到小排列
    
    new_df.sort_values(by=['数量'], ascending=False)

    通过输出的排序结果可以看出,房源数量位于前的区域分别是朝阳区、海淀区、丰台区。

    4.2 户型数量分析

    随着人们生活水平的提高,以及各住户的生活需求,开发商设计出了各种各样的户型供人们居住。接下来,我们来分析一下户型,统计租房市场中哪种户型的房源数量偏多,并筛选出数量大于50的户型。

    首先,我们定义一个函数来计算各种户型的数量,具体代码如下。

    # 定义函数,用于计算各户型的数量
    def all_house(arr):
        key = np.unique(arr)
        result = {}
        for k in key:
            mask = (arr == k)
            arr_new = arr[mask]
            v = arr_new.size
            result[k] = v
        return result
    
    # 获取户型数据
    house_array = file_data['户型']
    house_info = all_house(house_array)

    程序输出了一个字典,其中,字典的键表示户型的种类,值表示该户型的数量。

    使用字典推导式将户型数量大于50的元素筛选出来,并将筛选后的结果转换成 DataFrame对象,具体代码如下。

    # 使用字典推导式
    house_type = dict((key, value) for key, value 
    in house_info.items() if value > 50)
    show_houses = pd.DataFrame({'户型':[x for x in  house_type.keys()],
                      '数量':[x for x in house_type.values()]})

    为了能够更直观地看到户型数量间的差异,我们可以使用条形图进行展示,其中,条形图纵轴坐标代表户型种类,横坐标代表数量体代码如下

    import matplotlib.pyplot as plt
    
    house_type = show_houses['户型']
    house_type_num = show_houses['数量']
    plt.barh(range(11), house_type_num, height=0.7, color='steelblue', alpha=0.8)     
    plt.yticks(range(11), house_type)
    plt.xlim(0,2500)  # 把x轴坐标延长到2500
    plt.xlabel("数量")
    plt.ylabel("户型种类")
    plt.title("北京地区各户型房屋数量")
    for x, y in enumerate(house_type_num):
        plt.text(y + 0.2, x - 0.1, '%s' % y)
    plt.show()
    

    运行结果如下图所示。

    通过图可上以清晰地看出,整个租房市场中户型数量较多分别为“2室1厅”、“1室1厅”、“3室1厅”的房屋,其中,“2室1厅”户型的房屋在整个租房市场中是数量最多的。

    4.3 平均租金分析

    为了进一步剖析房屋的情况,接下来,我们来分析一下各地区目前的平均租金情况。计算各区域房租的平均价格与计算各区域户型数量的方法大同小异,首先创建一个 DataFrame对象,具体代码如下。

    # 新建一个DataFrame对象,设置房租总金额和总面积初始值为0
    
    df_all = pd.DataFrame({'区域':file_data['区域'].unique(),
                             '房租总金额':[0]*13,
                             '总面积(㎡)':[0]*13})
    

    接下来,按照“区域”一列进行分组,然后调用sum()方法分别对房租金额和房屋面积执行求和计算,具体代码如下:

    # 求总金额和总面积
    
    sum_price = file_data['价格(元/月)'].groupby(file_data['区域']).sum()
    sum_area = file_data['面积(㎡)'].groupby(file_data['区域']).sum()
    df_all['房租总金额'] = sum_price.values
    df_all['总面积(㎡)'] = sum_area.values

    计算出各区域房租总金额和总面积之后,便可以对每平方米的租金进行计算。在df_all对象的基础上增加一列,该列的名称为“每平方米租金(元)”,数据为求得的每平方米的平均价格,具体代码如下。

    # 计算各区域每平米房租价格,并保留两位小数
    
    df_all['每平米租金(元)'] = round(df_all['房租总金额'] / df_all ['总面积(㎡)'], 2)

    为了能更加全面地了解到各个区域的租房数量与平均租金,我们可以将之前创建的 new_df对象(各区域房源数量)与df_all对象进行合并展示,由于这两个对象中都包含“区域”一列,所以这里可以采用主键的方式进行合并,也就是说通过 merge()函数来实现,具体代码如下。

    # 合并new_df与df_all
    
    df_merge = pd.merge(new_df, df_all)

    合并完数据以后,就可以借用图表来展示各地区房屋的信息,其中,房源的数量可以用柱状图中的条柱表示,每平方米租金可以用折线图中的点表示,具体代码如下。

    num= df_merge['数量']   # 数量
    price=df_merge['每平米租金(元)'] # 价格
    l=[i for i in range(13)]
    
    lx=df_merge['区域']
    fig = plt.figure(figsize=(10, 8), dpi=100)
    
    # 显示折线图
    ax1 = fig.add_subplot(111) 
    ax1.plot(l, price,'or-',label='价格')  # "or-" 显示那个小红圆点
    for i,(_x,_y) in enumerate(zip(l,price)):
        plt.text(_x,_y,price[i])  
    ax1.set_ylim([0, 200])
    ax1.set_ylabel('价格')
    plt.legend(loc='upper left') 
    
    # 显示条形图
    ax2 = ax1.twinx()  # 显示次坐标轴ax2=ax1.twinx()
    plt.bar(l,num,alpha=0.3,color='green',label='数量')
    ax2.set_ylabel('数量')
    plt.legend(loc="upper right")
    plt.xticks(l,lx)
    
    plt.show()
    

    运行结果如下:

    从图中可以看出,西城区、东城区、海淀区、朝阳区的房租价格相对较高,这主要是因为东城区和西城区作为北京市的中心区,租金相比其他几个区域自然偏高一些,而海淀区租金较高的原因推测可能是海淀区名校较多,也是学区房最火热的地带,朝阳区内的中央商务区聚集了大量的世界500强公司,因此这四个区域的房租相对其他区域较高。

    4.4 面积区间分析

    下面我们将房屋的面积数据按照一定的规则划分成多个区间,看一下各面积区间的上情况,便于分析租房市场中哪种房屋类型更好出租,哪个面积区间的相房人数最多

    要想将数据划分为若干个区间,则可以使用Pame中的cut()函数来实现,首先,使用max()与min()方法分别计算出房屋面积的最大值和最小值,具体代码如下。

    # 查看房屋的最大面积和最小面积
    print('房屋最大面积是%d平米'%(file_data['面积(㎡)'].max()))
    print('房屋最小面积是%d平米'%(file_data['面积(㎡)'].min()))
    
    # 查看房租的最高值和最小值
    print('房租最高价格为每月%d元'%(file_data['价格(元/月)'].max()))
    print('房屋最低价格为每月%d元'%(file_data['价格(元/月)'].min()))
    

    在这里,我们参照链家网站的面积区间来定义,将房屋面积划分为8个区间。然后使用describe()方法显示各个区间出现的次数( counts表示)以及频率(freps表示),具体代码如下。

    # 面积划分
    area_divide = [1, 30, 50, 70, 90, 120, 140, 160, 1200]
    area_cut = pd.cut(list(file_data['面积(㎡)']), area_divide)
    area_cut_data = area_cut.describe()

    接着,使用饼图来展示各面积区间的分布情况,具体代码如下。

    area_percentage = (area_cut_data['freqs'].values)*100
    
    labels  = ['30平米以下', '30-50平米', '50-70平米', '70-90平米',
    '90-120平米','120-140平米','140-160平米','160平米以上']
    
    plt.figure(figsize=(20, 8), dpi=100)
    plt.axes(aspect=1)  # 显示的是圆形,如果不加,是椭圆形
    plt.pie(x=area_percentage, labels=labels, autopct='%.2f %%', shadow=True)
    plt.legend(loc='upper right')
    plt.show()
    

    运行结果如图所示:

    通过上图可以看出,50-70平方米的房屋在租房市场中占有率最大。总体看来,租户主要以120平方米以下的房屋为租住对象,其中50~70平方米以下的房屋为租户的首选对象。


    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    获取数据
    file_data = pd.read_csv("./data/链家北京租房数据.csv")
    file_data
    区域小区名称户型面积(㎡)价格(元/月)
    0东城万国城MOMA1室0厅59.11平米10000
    1东城北官厅胡同2号院3室0厅56.92平米6000
    2东城和平里三区1室1厅40.57平米6900
    3东城菊儿胡同2室1厅57.09平米8000
    4东城交道口北二条35号院1室1厅42.67平米5500
    5东城西营房2室1厅54.48平米7200
    6东城地坛北门1室1厅33.76平米6000
    7东城安外东河沿1室1厅37.62平米5600
    8东城清水苑1室1厅45.61平米6200
    9东城李村东里2室1厅57.35平米5700
    10东城幸福北里2室1厅51.15平米6500
    11东城保利蔷薇2室1厅97.11平米10000
    12东城东板桥西巷2室1厅52.86平米5800
    13东城本家润园三期2室1厅63.09平米7800
    14东城营房西街2室1厅62.95平米7500
    15东城新景家园西区1室1厅57.24平米7500
    16东城东花市北里东区2室1厅85.36平米8800
    17东城幸福家园一期5室2厅226.86平米29000
    18东城景泰西里西区1室1厅60.3平米6200
    19东城海晟名苑北区1室1厅70.86平米12000
    20东城和平新城一期2室1厅122.76平米14500
    21东城太华公寓2室2厅152.24平米17000
    22东城官书院2室1厅92.01平米16000
    23东城幸福家园二期2室1厅65.25平米7800
    24东城安外大街3号院1室1厅33.77平米5500
    25东城中海紫御公馆2室2厅90.15平米13000
    26东城海晟名苑北区1室0厅45.62平米9000
    27东城凯景铭座3室1厅156.2平米16000
    28东城永定门东街西里2室1厅53.26平米5000
    29东城西青年沟2室1厅51.88平米7300
    ..................
    8193顺义南竺园3室1厅90.47平米4200
    8194顺义石园东苑2室2厅102.94平米4000
    8195顺义建新北区2室1厅52.44平米3200
    8196顺义仓上小区3室1厅108.03平米3900
    8197顺义石园东区2室1厅91.93平米4100
    8198顺义裕龙三区1室1厅69.04平米3800
    8199顺义建新北区2室1厅50.04平米3600
    8200顺义东兴二区2室1厅81.98平米4000
    8201顺义万科四季花城2室1厅98.71平米6000
    8202顺义石园南区18号院1房间1卫58.7平米4000
    8203顺义建新北区2室1厅49.06平米3600
    8204顺义香悦四季3室1厅87.92平米4200
    8205顺义香悦四季3室2厅117.5平米6000
    8206顺义旭辉26街区3室1厅59平米4500
    8207顺义江山赋2室1厅97.38平米8800
    8208顺义樱花园六区2室2厅94.78平米4200
    8209顺义樱花园二区2室1厅68.76平米3500
    8210顺义樱花园六区2室2厅94.78平米3900
    8211顺义胜利小区2室1厅58.05平米3800
    8212顺义樱花园一区2室1厅79.59平米3900
    8213顺义江山赋2室1厅74.62平米5200
    8214顺义江山赋3室1厅104.03平米9500
    8215顺义恒华安纳湖2室1厅90.43平米3500
    8216顺义石园北区2室2厅90.67平米3700
    8217顺义江山赋3室2厅146.92平米17000
    8218顺义怡馨家园3室1厅114.03平米5500
    8219顺义旭辉26街区4房间2卫59平米5000
    8220顺义前进花园玉兰苑3室1厅92.41平米5800
    8221顺义双裕小区2室1厅71.81平米4200
    8222顺义樱花园二区1室1厅35.43平米2700

    8223 rows × 5 columns

    file_data.shape
    (8223, 5)
    file_data.info()

     
    file_data.describe()
    

    价格(元/月)
    count8223.000000
    mean9512.297823
    std9186.752612
    min566.000000
    25%4800.000000
    50%6800.000000
    75%10000.000000
    max150000.000000
    数据基本处理
    重复值和空值处理
    # 重复值
    # file_data.duplicated()
    
    file_data = file_data.drop_duplicates()
    file_data.shape
    (5773, 5)
    # 空值处理
    file_data = file_data.dropna()
    file_data.shape
    (5773, 5)
    数据转换类型
    面积数据类型转换
    file_data.head()

    # 单个值实现
    file_data["面积(㎡)"].values[0][:-2]
    '59.11'
    # 创建一个空的数组
    data_new = np.array([])
    
    data_area = file_data["面积(㎡)"].values
    
    for i in data_area:
        data_new = np.append(data_new, np.array(i[:-2]))
    data_area
    array(['59.11平米', '56.92平米', '40.57平米', ..., '92.41平米', '71.81平米',
           '35.43平米'], dtype=object)
    data_new
    array(['59.11', '56.92', '40.57', ..., '92.41', '71.81', '35.43'],
          dtype='<U32')
    # 转换data_new中的数据类型
    data_new = data_new.astype(np.float64)
    data_new
    array([59.11, 56.92, 40.57, ..., 92.41, 71.81, 35.43])
    file_data.loc[:, "面积(㎡)"] = data_new
    file_data.head()

    户型表达方式替换
    file_data
    区域小区名称户型面积(㎡)价格(元/月)
    0东城万国城MOMA1室0厅59.1110000
    1东城北官厅胡同2号院3室0厅56.926000
    2东城和平里三区1室1厅40.576900
    3东城菊儿胡同2室1厅57.098000
    4东城交道口北二条35号院1室1厅42.675500
    5东城西营房2室1厅54.487200
    6东城地坛北门1室1厅33.766000
    7东城安外东河沿1室1厅37.625600
    8东城清水苑1室1厅45.616200
    9东城李村东里2室1厅57.355700
    10东城幸福北里2室1厅51.156500
    11东城保利蔷薇2室1厅97.1110000
    12东城东板桥西巷2室1厅52.865800
    13东城本家润园三期2室1厅63.097800
    14东城营房西街2室1厅62.957500
    15东城新景家园西区1室1厅57.247500
    16东城东花市北里东区2室1厅85.368800
    17东城幸福家园一期5室2厅226.8629000
    18东城景泰西里西区1室1厅60.306200
    19东城海晟名苑北区1室1厅70.8612000
    20东城和平新城一期2室1厅122.7614500
    21东城太华公寓2室2厅152.2417000
    22东城官书院2室1厅92.0116000
    23东城幸福家园二期2室1厅65.257800
    24东城安外大街3号院1室1厅33.775500
    25东城中海紫御公馆2室2厅90.1513000
    26东城海晟名苑北区1室0厅45.629000
    27东城凯景铭座3室1厅156.2016000
    28东城永定门东街西里2室1厅53.265000
    29东城西青年沟2室1厅51.887300
    ..................
    8173顺义智地香蜜湾4房间2卫75.878000
    8174顺义香花畦家园4室2厅179.6512000
    8175顺义龙湖香醍漫步四区南区1室0厅38.962300
    8177顺义莫奈花园4室2厅241.7820000
    8181顺义裕龙三区3室1厅152.729000
    8183顺义万科城市花园4室2厅218.4415500
    8192顺义胜利小区1室1厅43.803000
    8193顺义南竺园3室1厅90.474200
    8200顺义东兴二区2室1厅81.984000
    8201顺义万科四季花城2室1厅98.716000
    8202顺义石园南区18号院1房间1卫58.704000
    8203顺义建新北区2室1厅49.063600
    8204顺义香悦四季3室1厅87.924200
    8205顺义香悦四季3室2厅117.506000
    8206顺义旭辉26街区3室1厅59.004500
    8207顺义江山赋2室1厅97.388800
    8208顺义樱花园六区2室2厅94.784200
    8209顺义樱花园二区2室1厅68.763500
    8210顺义樱花园六区2室2厅94.783900
    8211顺义胜利小区2室1厅58.053800
    8212顺义樱花园一区2室1厅79.593900
    8214顺义江山赋3室1厅104.039500
    8215顺义恒华安纳湖2室1厅90.433500
    8216顺义石园北区2室2厅90.673700
    8217顺义江山赋3室2厅146.9217000
    8218顺义怡馨家园3室1厅114.035500
    8219顺义旭辉26街区4房间2卫59.005000
    8220顺义前进花园玉兰苑3室1厅92.415800
    8221顺义双裕小区2室1厅71.814200
    8222顺义樱花园二区1室1厅35.432700

    5773 rows × 5 columns

    house_data = file_data["户型"]
    temp_list = []
    
    for i in house_data:
        # print(i)
        new_info = i.replace("房间", "室")
        temp_list.append(new_info)
    file_data.loc[:, "户型"] = temp_list
    file_data
    
    区域小区名称户型面积(㎡)价格(元/月)
    0东城万国城MOMA1室0厅59.1110000
    1东城北官厅胡同2号院3室0厅56.926000
    2东城和平里三区1室1厅40.576900
    3东城菊儿胡同2室1厅57.098000
    4东城交道口北二条35号院1室1厅42.675500
    5东城西营房2室1厅54.487200
    6东城地坛北门1室1厅33.766000
    7东城安外东河沿1室1厅37.625600
    8东城清水苑1室1厅45.616200
    9东城李村东里2室1厅57.355700
    10东城幸福北里2室1厅51.156500
    11东城保利蔷薇2室1厅97.1110000
    12东城东板桥西巷2室1厅52.865800
    13东城本家润园三期2室1厅63.097800
    14东城营房西街2室1厅62.957500
    15东城新景家园西区1室1厅57.247500
    16东城东花市北里东区2室1厅85.368800
    17东城幸福家园一期5室2厅226.8629000
    18东城景泰西里西区1室1厅60.306200
    19东城海晟名苑北区1室1厅70.8612000
    20东城和平新城一期2室1厅122.7614500
    21东城太华公寓2室2厅152.2417000
    22东城官书院2室1厅92.0116000
    23东城幸福家园二期2室1厅65.257800
    24东城安外大街3号院1室1厅33.775500
    25东城中海紫御公馆2室2厅90.1513000
    26东城海晟名苑北区1室0厅45.629000
    27东城凯景铭座3室1厅156.2016000
    28东城永定门东街西里2室1厅53.265000
    29东城西青年沟2室1厅51.887300
    ..................
    8173顺义智地香蜜湾4室2卫75.878000
    8174顺义香花畦家园4室2厅179.6512000
    8175顺义龙湖香醍漫步四区南区1室0厅38.962300
    8177顺义莫奈花园4室2厅241.7820000
    8181顺义裕龙三区3室1厅152.729000
    8183顺义万科城市花园4室2厅218.4415500
    8192顺义胜利小区1室1厅43.803000
    8193顺义南竺园3室1厅90.474200
    8200顺义东兴二区2室1厅81.984000
    8201顺义万科四季花城2室1厅98.716000
    8202顺义石园南区18号院1室1卫58.704000
    8203顺义建新北区2室1厅49.063600
    8204顺义香悦四季3室1厅87.924200
    8205顺义香悦四季3室2厅117.506000
    8206顺义旭辉26街区3室1厅59.004500
    8207顺义江山赋2室1厅97.388800
    8208顺义樱花园六区2室2厅94.784200
    8209顺义樱花园二区2室1厅68.763500
    8210顺义樱花园六区2室2厅94.783900
    8211顺义胜利小区2室1厅58.053800
    8212顺义樱花园一区2室1厅79.593900
    8214顺义江山赋3室1厅104.039500
    8215顺义恒华安纳湖2室1厅90.433500
    8216顺义石园北区2室2厅90.673700
    8217顺义江山赋3室2厅146.9217000
    8218顺义怡馨家园3室1厅114.035500
    8219顺义旭辉26街区4室2卫59.005000
    8220顺义前进花园玉兰苑3室1厅92.415800
    8221顺义双裕小区2室1厅71.814200
    8222顺义樱花园二区1室1厅35.432700

    5773 rows × 5 columns

    图表分析
    房源数量、位置分布分析
    file_data["区域"].unique()
    array(['东城', '丰台', '亦庄开发区', '大兴', '房山', '昌平', '朝阳', '海淀', '石景山', '西城',
           '通州', '门头沟', '顺义'], dtype=object)
    new_df = pd.DataFrame({"区域":file_data["区域"].unique(), "数量":[0]*13})
    new_df

    # 获取每个区域房源数量
    area_count = file_data.groupby(by="区域").count()
    new_df["数量"] = area_count.values
    new_df.sort_values(by="数量", ascending=False)

    户型数量分析
    house_data = file_data["户型"]
    house_data.head()
    0    1室0厅
    1    3室0厅
    2    1室1厅
    3    2室1厅
    4    1室1厅
    Name: 户型, dtype: object
    def all_house(arr):
        key = np.unique(arr)
        result = {}
        
        for k in key:
            mask = (arr == k)
            arr_new = arr[mask]
            v = arr_new.size
            result[k] = v
            
        return result    
    house_info = all_house(house_data)
    house_info
    {'0室0厅': 1,
     '1室0卫': 10,
     '1室0厅': 244,
     '1室1卫': 126,
     '1室1厅': 844,
     '1室2厅': 13,
     '2室0卫': 1,
     '2室0厅': 23,
     '2室1卫': 120,
     '2室1厅': 2249,
     '2室2卫': 22,
     '2室2厅': 265,
     '2室3厅': 1,
     '3室0卫': 3,
     '3室0厅': 12,
     '3室1卫': 92,
     '3室1厅': 766,
     '3室2卫': 48,
     '3室2厅': 489,
     '3室3卫': 1,
     '3室3厅': 10,
     '4室1卫': 15,
     '4室1厅': 58,
     '4室2卫': 24,
     '4室2厅': 191,
     '4室3卫': 5,
     '4室3厅': 9,
     '4室5厅': 2,
     '5室0卫': 1,
     '5室0厅': 1,
     '5室1卫': 3,
     '5室1厅': 7,
     '5室2卫': 7,
     '5室2厅': 49,
     '5室3卫': 3,
     '5室3厅': 24,
     '5室4厅': 1,
     '5室5厅': 1,
     '6室0厅': 1,
     '6室1卫': 1,
     '6室1厅': 1,
     '6室2厅': 5,
     '6室3卫': 2,
     '6室3厅': 6,
     '6室4卫': 2,
     '7室1厅': 1,
     '7室2厅': 2,
     '7室3厅': 3,
     '7室4厅': 1,
     '8室4厅': 2,
     '9室1厅': 2,
     '9室2厅': 1,
     '9室5厅': 2}
    # 去掉统计数量较少的值
    house_data = dict((key, value) for key, value in house_info.items() if value > 50)
    show_houses = pd.DataFrame({"户型": [x for x in house_data.keys()],
                  "数量": [x for x in house_data.values()]})
    show_houses

    # 图形展示房屋类型
    
    house_type = show_houses["户型"]
    house_type_num = show_houses["数量"]
    
    plt.barh(range(11), house_type_num)
    
    plt.yticks(range(11), house_type)
    plt.xlim(0, 2500)
    
    plt.title("北京市各区域租房数量统计")
    plt.xlabel("数量")
    plt.ylabel("房屋类型")
    
    # 给每个条上面添加具体数字
    for x, y in enumerate(house_type_num):
        # print(x, y)
        plt.text(y+0.5, x-0.2, "%s" %y)
    
    plt.show()

    平均租金分析
    df_all = pd.DataFrame({"区域": file_data["区域"].unique(),
                  "房租总金额": [0]*13,
                  "总面积": [0]*13})
    df_all

    file_data.head()
    

    sum_price = file_data["价格(元/月)"].groupby(file_data["区域"]).sum()
    sum_area = file_data["面积(㎡)"].groupby(file_data["区域"]).sum()
    df_all["房租总金额"] = sum_price.values
    df_all["总面积"] = sum_area.values
    df_all

    # 计算各个区域每平方米的房租
    df_all["每平米租金(元)"] = round(df_all["房租总金额"] / df_all["总面积"], 2)
    df_all

    df_merge = pd.merge(new_df, df_all)
    df_merge

    # 图形可视化
    
    num = df_merge["数量"]
    price = df_merge["每平米租金(元)"]
    lx = df_merge["区域"]
    l = [i for i in range(13)]
    
    fig = plt.figure(figsize=(10, 8), dpi=100)
    
    # 显示折线图
    ax1 = fig.add_subplot(111)
    ax1.plot(l, price, "or-", label="价格")
    for i, (_x, _y) in enumerate(zip(l, price)):
        plt.text(_x+0.2, _y, price[i])
    ax1.set_ylim([0, 160])   
    ax1.set_ylabel("价格")
    plt.legend(loc="upper right")
    
    # 显示条形图
    ax2 = ax1.twinx()
    plt.bar(l, num, label="数量", alpha=0.2, color="green")
    ax2.set_ylabel("数量")
    plt.legend(loc="upper left")
    plt.xticks(l, lx)
    
    
    plt.show()
    

    面积基本分析
    # 查看房屋的最大面积和最小面积
    print('房屋最大面积是%d平米'%(file_data['面积(㎡)'].max()))
    print('房屋最小面积是%d平米'%(file_data['面积(㎡)'].min()))
    
    # 查看房租的最高值和最小值
    print('房租最高价格为每月%d元'%(file_data['价格(元/月)'].max()))
    print('房屋最低价格为每月%d元'%(file_data['价格(元/月)'].min()))
    房屋最大面积是1133平米
    房屋最小面积是11平米
    房租最高价格为每月150000元
    房屋最低价格为每月566元
    # 面积划分
    area_divide = [1, 30, 50, 70, 90, 120, 140, 160, 1200]
    area_cut = pd.cut(list(file_data["面积(㎡)"]), area_divide)
    area_cut_num = area_cut.describe()
    area_cut_num

    area_per = (area_cut_num["freqs"].values)*100
    
    labels  = ['30平米以下', '30-50平米', '50-70平米', '70-90平米',
    '90-120平米','120-140平米','140-160平米','160平米以上']
    
    plt.figure(figsize=(20, 8), dpi=100)
    # plt.axes(aspect=1)
    
    plt.pie(x=area_per, labels=labels, autopct="%.2f %%")
    
    
    plt.legend()
    plt.show()


    展开全文
  • 宠物小精灵可视化 使用Seaborn和Matplotlib库对数据进行深度可视化。 直方图,条形图,小提琴图,饼图,热图,箱形图,条形图,群体图....用于分析和可视化神奇宝贝的各种属性。
  • sns.distplot(数据序列,bins=10,color='k'):直方图+密度图 import seaborn as sns fig,axes = plt.subplots(2,2, figsize=(6,5)) df[['A','B']].plot.hist(stacked=True, color=plt.cm.Pastel1([0,1]), ax=axes[0,0...

    sns:直方图和密度图、散点图和散点矩阵

    df/s.plot()参数

    df = pd.read_csv()
    Series.boxplot()
    df.plot(
    	【数据/图类型】:
    	x='col1',y='col2'指定xy,也可以不用
    	kind='',		无kind则默认折线图
    	logy, 			y轴上是否转化为log
    	yerr,xerr,		标记误差
    
    	【图例/标签等】:
    	ax,				绘制的图的子图位置
    	figsize,		图像大小
    	labels,			用作图例的标签
    	legend,			添加一个subplot的图例,默认True
    
    	【样式】:
    	color,
    	style,			颜色、标记、线形
    	alpha,			填充不透明度
    	colormap=		str类性,直接写名称
    
    	【轴/刻度】:
    	use_index,		是否将对象的索引用作X轴刻度标签,默认是
    	rot,			旋转刻度标签
    	xticks/yticks,	刻度值
    	xlim/ylim,		范围
    	x_compat=True	对于时间序列,由原来简单标记变为显示出‘2019-02’的形式
    	grid,			是否显示轴网格线(默认打开)
    
    	【子图】:
    	subplots,				是否将各列绘制到单独的subplot中,默认False
    	sharex/sharey,			是否共用一个X轴,包括刻度和范围,与subplots共用
    	layout=()				与subplots同用,变为几行几列
    
    	sort_columns,			以字母表顺序绘制各列,默认使用当前列顺序
    	secondary_y=True		是否在原有坐标下建立次坐标轴,True,False
    	)
    kind可选类别:
    'box':箱线		'line':折线		'bar':柱形图	'barh':条形
    'kde':密度图	'area':面积图	'pie':饼图		'hist':直方图
    'density':密度图				'scatter':散点  'hexbin':
    如果未指定xy,DataFrame将对象的索引用作X轴刻度标签,为每列绘制一条线,自动创建图例;
    

    1箱线与面积图

    df = pd.DataFrame(np.random.randint(1,10,(50,2)), columns=['A','B'])
    df['C'] = np.random.choice(['red', 'blue'], size=50)
    df.head()
    	A	B	C
    0	8	6	blue
    1	1	7	blue
    2	1	3	red
    3	8	4	red
    4	6	9	blue
    colors={'boxes': 'DarkGreen', 'whiskers': 'DarkOrange', 'medians': 'DarkBlue', 'caps': 'Gray'}:各位置颜色
    df.plot.box(color=colors, sym='r+', vert=True, positions=[]) 
    # 每列绘制一个箱线,sym是异常值样式, vert=True表示默认的竖向, positions可确定位置
    

    在这里插入图片描述

    df.boxplot():每列绘制一个箱线
    df.boxplot(by=[分类序列1, 分类序列2]):每个序列根据分类(组合)绘制一个子图,几个列就有几个子图
    
    df.boxplot(by=['C'])
    

    在这里插入图片描述

    df.groupby(['C']).boxplot():根据类别绘图,有几类就有几个子图(和上面相反)
    

    在这里插入图片描述

    2面积图

    df.plot.area(stacked=True):默认是堆积的面积图
    
    df[['A','B']].plot.area(stacked=True, color=plt.cm.Pastel1([0,1]))
    

    在这里插入图片描述

    3柱状图和条形图

    df.plot.bar/barh(color=[], stacked=True):堆积列数据到一个X类别下,否则一个X类别下多条柱形
    s.plot.bar/barh()
    
    df.index = pd.date_range('2021-02-04',periods=50,freq='D')
    df.head()
    			A	B	C
    2021-02-04	8	6	blue
    2021-02-05	1	7	blue
    2021-02-06	1	3	red
    2021-02-07	8	4	red
    2021-02-08	6	9	blue
    
    df1 = df.iloc[:10,:2]
    fig,axes=plt.subplots(1,2, figsize=(6,4))
    df1.plot.barh(ax=axes[0],color=plt.cm.Pastel1([0,1]), legend=False)
    axes[0].set_yticks(list(range(len(df1))))
    axes[0].set_yticklabels(df1.index.strftime('%m-%d'))
    axes[0].set_ylabel(u'2021年',rotation='horizontal',y=0)
    
    df1.plot.bar(stacked=True,ax=axes[1],color=plt.cm.Pastel1([0,1]), legend=False)
    axes[1].set_xticks(list(range(len(df1))))
    axes[1].set_xticklabels(df1.index.strftime('%m-%d'))
    axes[1].set_xlabel(u'2021年', loc='right')
    plt.legend(bbox_to_anchor=(1,0.8))
    

    在这里插入图片描述

    4直方图和密度图

    【直方图】:
    s/df.plot.hist(bins=10, stack=False, orientation='horizontal', cumulative=False):
     直方图        分段数量     是否堆积       方向                        是否累计
    
    df.hist():为每列单独画一个图,上面的是画在一个图里
    s.hist(by=分组序列):传入长度=s的分组序列,结果将分组成几个子图
    
    【密度图】:
    s/df.plot.kde()
    s.plot.density():密度曲线图
    sns.distplot(数据序列,bins=10,color='k'):直方图+密度图
    
    import seaborn as sns
    
    fig,axes = plt.subplots(2,2, figsize=(6,5))
    df[['A','B']].plot.hist(stacked=True, color=plt.cm.Pastel1([0,1]), ax=axes[0,0], title=u'df堆积频率直方图')
    axes[0,0].grid(axis='y', linewidth=0.3)
    
    df['A'].plot.hist(orientation='horizontal', cumulative=True, color=plt.cm.Pastel1([0]), ax=axes[0,1], title=u'累计频率直方图',legend=False)
    
    df[['A','B']].plot.kde(color=plt.cm.Pastel1([0,1]), ax=axes[1,0], title=u'df密度图kde')
    axes[1,0].legend(loc='upper right')
    
    sns.histplot(df['A'], bins=10, ax=axes[1,1])
    axes[1,1].set_title(u'sns密度+直方图')
    axes[1,1].legend(['A'],bbox_to_anchor=(1,0.8))
    
    plt.subplots_adjust(hspace=0.38,wspace=0.35)
    

    在这里插入图片描述

    df.hist(column='A',by='C')
    

    在这里插入图片描述

    5散点图及矩阵

    【散点图】:
    df.plot.scatter(x='A',y='B',label='g1', c='C', cmap='autumn',s=df['C']*20)
    c和cmap不同同时存在,设置c则表示根据数值大小颜色有深浅。
    绘制两个/多个散点图:
    ax = df.plot.scatter(颜色样式标签等)
    df.plot.scatter(颜色样式标签等, ax=ax)
    df.plot.scatter(颜色样式标签等, ax=ax)
    ...
    
    sns.regplot('x数据','y数据',data='df'):散点图+线性回归的线,也可以没有data来源,只写两个序列
    
    【散点矩阵】:
    from pandas.plotting import scatter_matrix
    scatter_matrix(df, diagonal='kde'):指定对角线图的类型
    sns.pairplot(df,diag_kind='kde',plot_kws={'color':'','alpha':}):散点图矩阵,diag_kind指定对角线图形类别,plot_kws为非对角图的配置
    -------------------------------------------------------------------
    【散点图】:
    df = pd.DataFrame(np.random.randn(1000, 3), columns=['a', 'b', 'c'])
    fig,ax=plt.subplots(1,1)
    df.plot.scatter(x='a',y='b',s=abs(df['b'])*20,ax=ax,color='#66CCFF',label='b')
    plt.legend()
    df.plot.scatter(x='a',y='c', s=abs(df['c'])*20,ax=ax,label='c',color='#FF99CC')
    plt.legend()
    plt.ylabel('b/c')
    
    【散点矩阵】:
    from pandas.plotting import scatter_matrix
    scatter_matrix(df, diagonal='kde')
    sns.pairplot(df, diag_kind='kde')
    

    在这里插入图片描述

    scatter_matrix(df, diagonal='kde')
    

    在这里插入图片描述

    sns.pairplot(df, diag_kind='kde')
    

    在这里插入图片描述

    6六边蜂箱图

    适用于数据量大的情况, 类似散点图
    df.plot.hexbin(x='col1', y='col2', gridsize=30):计算每对(x,y)值附近的点的数量
    df.plot.hexbin(x='col1', y='col2', C='col3', reduce_C_function=函数, gridsize=30):以C中的值作为每对(x,y)对应的值,reduce_C_function应用于每个小区域的数据,得到一个标量,和C联用就是对'col3'的数据应用函数
    
    df = pd.DataFrame(np.random.rand(360,360)+np.sin(np.linspace(-np.pi/4,(4/3)*np.pi,360)).reshape(1, 360).repeat(360, axis=0)*30, 
                      columns=np.linspace(0, 180, 360), index=np.linspace(-90,90,360))
    df.index.name='经度'
    df.columns.name='纬度'
    df = df.stack().reset_index()
    df.columns = ['经度', '纬度', '温度']
    df
    		经度	纬度	温度
    0		-90.0	0.000000	-20.895695
    1		-90.0	0.501393	-20.362729
    2		-90.0	1.002786	-19.963455
    3		-90.0	1.504178	-19.530852
    4		-90.0	2.005571	-19.255508
    ...		...		...			...
    129595	90.0	177.994429	-24.782752
    129596	90.0	178.495822	-25.135172
    129597	90.0	178.997214	-25.044194
    129598	90.0	179.498607	-24.899114
    129599	90.0	180.000000	-25.623183
    
    fig,ax=plt.subplots(1,2, figsize=(12,5))
    df.plot.hexbin(x='经度',y='纬度', gridsize=25,ax=ax[0])
    df.plot.hexbin(x='经度',y='纬度',gridsize=25, C='温度', reduce_C_function=np.max,ax=ax[1])
    

    在这里插入图片描述

    7饼图

    s.plot.pie(labels=[], colors=[], autopct='%.2f''%1.2%%'):类别为index,再根据值绘图
    df.plot.pie(y='col1'):根据某一列绘图
    df.plot.pie(subplots=True, legend=False):绘制全部列,取消图例
    可使用小数表示百分比,如果和<1,饼图是不完整的
    
    df = pd.DataFrame({'mass': [0.330, 4.87 , 5.97], 'radius': [2439.7, 6051.8, 6378.1]},  index=['Mercury', 'Venus', 'Earth'])
    		mass	radius
    Mercury	0.33	2439.7
    Venus	4.87	6051.8
    Earth	5.97	6378.1
    df.plot.pie(subplots=True, figsize=(5, 5), colors=plt.cm.Pastel1([0,1,2]), legend=False)
    plt.legend(df.index, bbox_to_anchor=(1,0.4),fontsize=8)
    plt.subplots_adjust(wspace=0.4)
    

    在这里插入图片描述

    对于缺失值的处理

    类型			处理
    line			保留缺口
    line(stacked)	填充0
    bar				填充0
    scatter			删除
    histogram		删除(列向)
    box				删除(列向)
    area			填充0
    kde				删除(列向)
    hexbin			删除
    pie				填充0
    
    展开全文
  • How can I subplot 'pie1' in 'fig', so it be located at 'the first' ... this is how I am doing it but it doesn't work outimport pandas as pdimport numpy as npimport seaborn as snsimport plotly.of...

    How can I subplot 'pie1' in 'fig', so it be located at 'the first' position. this is how I am doing it but it doesn't work out

    import pandas as pd

    import numpy as np

    import seaborn as sns

    import plotly.offline as pyp

    import plotly.graph_objs as go

    from plotly import tools

    import plotly.plotly as py

    from plotly.offline import iplot,init_notebook_mode

    from IPython.core.display import HTML

    import plotly.io

    df1=pd.read_excel('file.xlsx',sheet_name='sheet1',index=False)

    con_pivot=pd.pivot_table(con,index='Category',values=('Payment'),aggfunc='sum',margins=True,margins_name='Total')

    fig = tools.make_subplots(rows=2, cols=2, subplot_titles=('The first','3','2','4'))

    pie1=go.Pie(labels=con_pivot.index,values=con_pivot.values)

    fig.append_trace(pie1,1,1)

    pyo.plot(fig)

    Any help help will be appreciated.

    Thank you

    解决方案

    The way to achieve the side by side pie charts using the make_subplots function from plotly would be the following (Many thanks to @Oysiyl for the input data):

    from plotly.subplots import make_subplots

    import plotly.graph_objects as go

    from plotly.offline import plot

    fig = make_subplots(rows=1, cols=2, specs=[[{"type": "pie"}, {"type": "pie"}]])

    fig.add_trace(go.Pie(

    values=[16, 15, 12, 6, 5, 4, 42],

    labels=["US", "China", "European Union", "Russian Federation",

    "Brazil", "India", "Rest of World"

    ],

    domain=dict(x=[0, 0.5]),

    name="GHG Emissions"),

    row=1, col=1)

    fig.add_trace(go.Pie(

    values=[27, 11, 25, 8, 1, 3, 25],

    labels=["US", "China", "European Union", "Russian Federation",

    "Brazil", "India", "Rest of World"

    ],

    domain=dict(x=[0.5, 1.0]),

    name="CO2 Emissions"),

    row=1, col=2)

    plot(fig)

    8XCAK.png

    展开全文
  • 上部分介绍了pie以及kdeplot、distplot、jointplot、pairplot的用法分别绘制出数据的饼图、核密度分布图、柱状图、散点图、以及用jointplot绘制组合图。下面开始总结(散点图(二维,三维),折线图,(并列,叠加)...

    上部分介绍了pie以及kdeplot、distplot、jointplot、pairplot的用法分别绘制出数据的饼图、核密度分布图、

    柱状图、散点图、以及用jointplot绘制组合图。

    下面开始总结(散点图(二维,三维),折线图,(并列,叠加)柱状图,三维曲面图,箱线图的画法):

    (一)散点图:(relplot, scatterplot)

    '''

    seaborn.relplot(x=None, y=None, hue=None, size=None, style=None, data=None, row=None, col=None, col_wrap=None, row_order=None, col_order=None, palette=None, hue_order=None, hue_norm=None, sizes=None, size_order=None, size_norm=None, markers=None, dashes=None, style_order=None, legend='brief', kind='scatter', height=5, aspect=1, facet_kws=None, **kwargs)

    '''

    # -*- coding: utf-8 -*-

    import seaborn as sns

    import matplotlib.pyplot as plt

    import pandas as pd

    from scipy.stats import pearsonr,norm

    data = pd.read_csv('anscombe.csv')

    print(data.head())

    sns.set_context('paper')

    sns.set_style('ticks',{'font.sans-serif':['simhei','Arial']})

    pal = sns.husl_palette(n_colors=4,l = .7)

    sns.relplot(x = 'x', y = 'y', data = data, hue = 'dataset',style = 'dataset',sizes = (100,100),palette = pal)

    plt.suptitle("不同组的x与y之间的关系")

    plt.show()

    996313-20200622155428636-331997265.png不同组相同style,都是圆形;

    996313-20200622155554754-1280191593.png不同组不同style。

    显然我们的目的不仅仅是观察散点分布,更重要的是为了寻求x与y之间以及不同组之间的关系。

    我们对每一组的(x,y)连起来形成一个折线图,仅仅需要将kind = 'scatter'(默认)改为 kind = 'line';

    可得图:

    996313-20200622160642325-1665537525.png

    可以看出第二组数据点形成的曲线近似于抛物线轨迹,第四组数据点都在直线上(垂直于x的直线,说明y与x无关,因为有一个点偏离较远所以导致折线图出现这种情况),而第一组和第三组,线性不是很明显,但是这两组y与x呈明显的正相关关系。

    现在我们需要对这几组数据用回归拟合,找出每组内x与y之间的函数关系。

    from scipy.stats importlinregress

    data= pd.read_csv('anscombe.csv')

    print(data.head())

    sns.set_context('paper')

    sns.set_style('ticks',{'font.sans-serif':['simhei','Arial']})

    cls= ['I','II','III','IV']

    markers= ['o','x','^','*']

    c= ['r','b','g','y']

    data= data[data['x']<18] #删除异常值,因为我们知道百分之95的数据的x都在(4,18)区间内,离群点对线性回归影响很大,特别是当数据量较小的时候

    f= plt.figure(figsize=(8,6))for i in range(4):

    dt= data[data['dataset']==cls[i]]

    k,b,r,p,std= linregress(dt['x'],dt['y'])

    flag= 1

    ifnp.isnan(k):

    k,b,r,p,std= linregress(dt['y'],dt['x'])

    flag= 0plt.scatter(dt['x'],dt['y'],marker=markers[i],label =cls[i])ifflag:

    plt.plot(dt['x'],k*dt['x']+b,color = c[i],label =cls[i])else:

    plt.plot(k*dt['y']+b,dt['y'],color = c[i],label =cls[i])

    flag= 1plt.legend(loc= 'upper left')

    plt.suptitle('线性拟合各组数据')

    plt.show()

    996313-20200622175330520-1714856918.png

    箱线图:

    我们可以根据box图或者violin图来看每一组数据分布的区间,可以方便我们判断离群点:

    data = pd.read_csv('anscombe.csv')

    print(data.head())

    sns.set_context('paper')

    sns.set_style('ticks',{'font.sans-serif':['simhei','Arial']})

    f= plt.figure(figsize=(8,6))

    f.add_subplot(221)

    sns.boxplot('dataset','x',data = data, palette = 'husl')

    plt.xlabel('(a)')

    f.add_subplot(222)

    sns.boxplot('dataset','y',data = data, palette='husl')

    plt.xlabel('(b)')

    f.add_subplot(223)

    sns.violinplot('dataset','x',data = data, palette = 'husl')

    plt.xlabel('(c)')

    f.add_subplot(224)

    sns.violinplot('dataset','y',data = data, palette = 'husl')

    plt.xlabel('(d)')

    plt.tight_layout()

    plt.show()

    996313-20200622182334614-834093286.png

    由图(c)可以看出第IV组的大部分的数据的x集中在8一点,而y分布与6周围,可以知道y和x的相关性很小,通过(a) (b)我们也可以看到离群点,

    (a)至少有一个离群点,分布在x>18范围内,(b)至少有里两个离群点,分布在y>12范围内。

    我们可以根据这个来删掉离群点,使得拟合结果更可信。

    三维散点图:

    先看三维曲线图:

    importmatplotlib as mpl

    from mpl_toolkits.mplot3dimportAxes3Dimportnumpy as npimportmatplotlib.pyplot as plt

    mpl.rcParams['legend.fontsize'] = 10fig=plt.figure()

    ax= fig.gca(projection='3d')

    theta= np.linspace(-4 * np.pi, 4 * np.pi, 100) #变量theta,决定(x,y,z),所以形成的图形为三维空间中的一维曲线(z与theta是呈线性关系的,绘出100个点。

    z= np.linspace(-2, 2, 100)

    r= z ** 2 + 1x= r *np.sin(theta)

    y= r *np.cos(theta)

    ax.plot(x, y, z, label='curve',color = 'g')

    ax.legend()

    plt.show()

    996313-20200622184317847-1744376165.png

    再看三维散点图:

    from mpl_toolkits.mplot3d importAxes3Dimportmatplotlib.pyplot as pltimportnumpy as np

    from matplotlibimportcm

    plt.rcParams['font.family'] = ['Arial Unicode MS'] # 用来正常显示中文标签

    plt.rcParams['axes.unicode_minus'] =False # 用来正常显示负号

    sns.set_style('whitegrid', {'font.sans-serif': ['Arial Unicode MS', 'Arial']})

    #用来解决中文方块化的问题

    x= np.random.normal(0,2,size = (3,50))

    y= np.random.normal(4,2,size = (3,50))

    fig= plt.figure(figsize=(10,5))

    ax1= fig.add_subplot(121, projection='3d')

    ax1.scatter(x[0],x[1],x[2],color = 'r',marker = 'o',label = '红点')

    ax1.scatter(y[0],y[1],y[2],color = 'b',marker = '^',label = '蓝点')

    ax1.legend()

    ax1.set_xlabel('X')

    ax1.set_ylabel('Y')

    ax1.set_zlabel('Z')

    ax2= fig.add_subplot(122,projection='3d')

    ax2.scatter(x[0],x[1],x[2],color = 'r',marker = 'o',label = '红点')

    ax2.scatter(y[0],y[1],y[2],color = 'b',marker = '^',label = '蓝点')

    x1= np.linspace(-5,5,100)

    y1= np.linspace(-3,8,100)

    x1,y1=np.meshgrid(x1,y1)

    z1= 6*np.ones(shape = (100,100)) - x1 -y1

    ax2.plot_surface(x1,y1,z1,cmap=cm.coolwarm,

    rstride=1, # rstride(row)指定行的跨度

    cstride=1, # 列跨度

    linewidth= 0, #线宽最低

    antialiased=True) #抗锯齿打开

    ax2.legend()

    ax2.set_xlabel('X')

    ax2.set_ylabel('Y')

    ax2.set_zlabel('Z')

    plt.show()

    996313-20200622210644297-1911478364.png

    可以看出x + y + z = 6的平面刚好能够把红点和蓝点区分开。

    因为红点呈中心为原点的正态分布,蓝点呈中心为(4,4,4)的正态分布,

    x+y+z = 6刚好是过两个中心中点的垂直平面,可以将两个正态分布的散点区分开。

    接下来我们要绘制x^2 - y^2 = z的图像 (马鞍面)

    三维曲面图:

    from mpl_toolkits.mplot3d importAxes3Dimportmatplotlib.pyplot as pltimportnumpy as np

    from matplotlibimportcm

    from matplotlib.tickerimportLinearLocator, FormatStrFormatter

    plt.rcParams['font.family'] = ['Arial Unicode MS'] # 用来正常显示中文标签

    plt.rcParams['axes.unicode_minus'] =False # 用来正常显示负号

    sns.set_style('whitegrid', {'font.sans-serif': ['Arial Unicode MS', 'Arial']})

    #用来解决中文方块化的问题

    x= np.linspace(-5,5,100)

    y= np.linspace(-5,5,100)

    x,y=np.meshgrid(x,y)

    z= x**2-y**2f= plt.figure(figsize=(5,4))

    ax= f.add_subplot(111,projection = '3d')

    ax.plot_surface(x, y, z, cmap=plt.get_cmap('rainbow'), rstride = 4,cstride = 4,

    linewidth=0, antialiased=False)

    ax.set_zlim(-20, 20)

    ax.zaxis.set_major_locator(LinearLocator(11)) #z方向上均匀分成11-1=10份,即找11个分点,

    ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) #分节点的值保留两位小数

    plt.show()

    996313-20200622212839936-395730192.png

    可以看出来当行跨度、列跨度为4的时候,划分曲线显得十分明显,使得整个曲面呈网格状。

    另外我们能在plt.show()前面加上f.colorbar(surf, shrink=.5, aspect=5) #shrink越小,表示colorbar越小

    便可以在右边绘制一个colorbar:

    996313-20200622214011051-1444538412.png

    我们从图中也可以看出相近的颜色的点高度都是相同的,我们能否直接绘制等高线呢?

    当然可以!

    from mpl_toolkits.mplot3d importaxes3dimportmatplotlib.pyplot as plt

    from matplotlibimportcm

    from matplotlib.tickerimportLinearLocator, FormatStrFormatter

    plt.rcParams['font.family'] = ['Arial Unicode MS'] # 用来正常显示中文标签

    plt.rcParams['axes.unicode_minus'] =False # 用来正常显示负号

    sns.set_style('whitegrid', {'font.sans-serif': ['Arial Unicode MS', 'Arial']})

    #用来解决中文方块化的问题

    x= np.linspace(-5,5,100)

    y= np.linspace(-5,5,100)

    x,y=np.meshgrid(x,y)

    z= x**2-y**2f= plt.figure(figsize=(5,4))

    ax= f.add_subplot(111,projection = '3d')

    surf= ax.plot_surface(x, y, z, cmap=cm.coolwarm, rstride = 4,cstride = 4,

    linewidth=0, antialiased=False)

    cset= ax.contour(x, y, z, zdir = 'z',offset = 30, cmap=cm.coolwarm, antialiased=False)

    ax.set_zlim(-20, 20)

    ax.zaxis.set_major_locator(LinearLocator(11)) #z方向上均匀分成11-1=10份,即找11个分点,

    ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) #分节点的值保留两位小数

    ax.set_xlabel('X')

    ax.set_ylabel('Y')

    ax.set_zlabel('Z')

    f.colorbar(surf, shrink=.5,aspect = 5)

    plt.show()

    996313-20200622215559030-1558805929.png

    叠加柱状图(用处较大):

    importnumpy as npimportmatplotlib.pyplot as plt

    plt.rcParams['font.family'] = ['Arial Unicode MS'] # 用来正常显示中文标签

    plt.rcParams['axes.unicode_minus'] =False # 用来正常显示负号

    sns.set_style('ticks', {'font.sans-serif': ['Arial Unicode MS', 'Arial']}) #用来解决中文方块化的问题

    N= 13#含有13组数据 每一组又分为三类A B C,每一类的频数记录其中

    A= (52, 49, 48, 47, 44, 43, 41, 41, 40, 38, 36, 31, 29)

    B= (38, 40, 45, 42, 48, 51, 53, 54, 57, 59, 57, 64, 62)

    d=[]for i in range(0, len(A)):

    sum= A[i] +B[i]

    d.append(sum)

    C= (10, 11, 7, 11, 8, 6, 6, 5, 3, 3, 7, 5, 9)

    ind=np.arange(N) #ind表示横轴坐标

    width= 0.4 #条形宽度设为0.4p1= plt.bar(ind, A, width, color = '#636e72')

    p2= plt.bar(ind, B, width, bottom=A, color = '#0984e3')

    p3= plt.bar(ind, C, width, bottom=d, color = '#fdcb6e') #最上面一层应该是前面那个相加得到的d作为下限

    plt.ylabel('频数')

    plt.title('不同组别各类数目分布')

    plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9', 'G10', 'G11', 'G12', 'G13'))

    plt.yticks(np.arange(0, 81, 20))

    plt.legend((p1[0], p2[0], p3[0]), ('A', 'B', 'C'), loc = 'upper right', bbox_to_anchor = (1.13,1.02)) #用两个元组表示legend标签,p[0]表示该图所拥有的颜色

    plt.show()

    996313-20200622223238249-609951388.png

    可以看出B类别在每个组都比较多,而A类别在每个组都比较少。

    综上就是Python绘图主要用的一些函数及其实例,后面会更新一些有关机器学习算法的总结,大家一起学习,一起进步~

    展开全文
  • Seaborn:Python

    2020-08-06 13:14:41
    Seaborn is a data visualization library built on top of matplotlib and closely integrated with pandas data structures in Python. Visualization is the central part of Seaborn which helps in exploration...
  • 本文介绍seaborn绘制分面图的底层:seaborn.FacetGrid
  • seaborn画饼图

    万次阅读 2017-12-10 16:29:50
    (一)饼图:1)用到的方法:matplotlib.pyplot.pie() 2)参数解析:pie(x, explode=None, labels=None, colors=('b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'), autopct=None, pctdistance=0.6, shadow=False, ...
  • 数据可视化总结——matplotlib、seaborn导包matplotlib基本参数折线图绘制直方图 hist(), plt.bar()绘制水平方向的柱状图饼图散点图箱线图seaborn基本参数直方图和密度曲线图密度曲线图毛毯图散点图catplot()如果...
  • 今天,我们就来了解一下python强大的绘图库——Matplotlib及Seaborn的使用。首先我们先来了解一下这两个强大的库。Matplotlib支持 Python 语言的开源绘图库(可以说是python里最优秀的绘图库了),因为其支...
  • 因此,作为替代,推荐一开始使用SeabornSeaborn本质上使用Matplotlib作为核心库(就像Pandas对NumPy一样)。seaborn有以下几个优点: 默认情况下就能创建赏心悦目的图表。 创建具有统计意义的图。 能理解...
  • Seaborn是Python中的一个库,主要用于生成统计图形。 Volodymyr Hryshchenko在Unsplash上拍摄 ​ Seaborn是构建在matplotlib之上的数据可视化库,与Python中的pandas数据结构紧密集成。可视化是Seaborn的核心部分...
  • 1 饼图知识 饼图:用于表示不同分类的占比情况,通过弧度大小来对比各种分类。 特点:分类数据的占比情况(占比) 饼图广泛得应用在各个领域,用于表示不同分类的占比情况,通过弧度大小来对比各种分类。饼图通过将一...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,481
精华内容 592
关键字:

seaborn饼图