Python 数据框的堆积面积图

Stacked Area plot for Python Dataframe

我有一个包含两列的数据框 (df):'Foundation Type',其中有 4 种类型的地基(竖井、桩、组合、传播),另一列 'Vs30' 具有不同的值参数 Vs30。每行代表一座桥,具有一种基础类型和一个 Vs30 值。

首先,我在 df 中创建一个新列 'binVs30',将 'Vs30' 的每个元素转换为不同的 bin,它有 5 种不同的范围([0-200],[200- 400]...[800-1000]).

df['binVs30'] = pd.cut(df.Vs30, bins=np.arange(0, 1100, 200))

然后,我创建了一个堆积面积图,代码如下:

color_table = pd.crosstab(df['binVs30'], df['Foundation Type'], dropna=False)
ax = color_table.plot(kind='area', figsize=(8, 8), stacked=True, rot=0)
display(ax)
plt.xlabel('')
plt.ylabel('Frequency', fontsize=12)
plt.legend(title='Foundation Type', loc='upper right')
plt.title('Column Database', fontsize='20')
plt.show()

Resulting Picture

生成的图片显示了一些不应该存在的额外垃圾桶。因此,我必须通过手动添加以下代码来修复 xticks:

locs, labels = plt.xticks()
    plt.xticks(locs, ['','0-200','','200-400','','400-600','','600-800','','800-1000'], fontsize=10, rotation=45)

xticks-fixed Picture

为什么 Python 会创建那些不应该存在的额外垃圾桶?这是 Python 的错误吗?因为如果我将其更改为堆积条形图,问题就会消失。有没有一种方法可以通过不手动添加 bin 代码来修复它?

还有另外两个问题,如何为面积图添加边缘颜色?类似于:

color_table.plot(kind='area', figsize=(8, 8), stacked=True, edgecolor='black', legend=None, rot=0)

命令 edgecolor='black' 在堆积面积图中不起作用。

而且,如果我想为 'Vs30' 创建 bin,例如 ([0-200],[200-400]...[>800])。有什么办法可以做到吗?由于我创建 'binVs30' 列的方式不允许我创建一个 '>800' 的容器。

谢谢。

这里有几个问题。首先是关于在 pd.cut() 中包含一个 open-ended bin。您可以使用 np.inf 捕获最后一个容器中的所有内容并为其分配自定义标签。其次,由于您已经在使用 matplotlib,我建议您直接使用其堆积图,而不是通过 pandas。然后你可以毫无问题地使用 edgecolor 参数。

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

df = pd.DataFrame(data={
    "foundation" : np.random.choice(list("ABCD"), 1000),
    "binVs30"    : np.random.randint(0, 1200, 1000)
})

bins = [0, 200, 400, 600, 800, np.inf]
labels = ["0-199", "200-399", "400-599", "600-799", "800+"]

df["bins"] = pd.cut(
    df["binVs30"], bins=bins, labels=labels,
    right=False, include_lowest=True)

stack_data = pd.crosstab(df['bins'], df['foundation'], dropna=False)

stack_array = stack_data.values.T.tolist()

pal = sns.color_palette("Set1")
plt.figure(figsize=(8,4))

plt.stackplot(
    labels, stack_array, labels=list("ABCD"),
    colors=pal, alpha=0.4, edgecolor="black")

plt.legend(loc='upper left')
plt.show()