pandas 通过重叠两个 Dataframe 为每个组/ID创建子图

svdrlsy4  于 2023-06-20  发布在  其他
关注(0)|答案(2)|浏览(96)

我有下面两个dataframe:

#Load the required libraries
import pandas as pd
import matplotlib.pyplot as plt

#Create dataset_1
data_set_1 = {'id': [1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,
               2, 2, 2, 2, 2, 2, 2,
               3, 3, 3, 3, 3, 3, 3,3,
               4, 4, 4, 4, 4,4,],
        'cycle': [0.0, 0.2,0.4, 0.6, 0.8, 1,1.2,1.4,1.6,1.8,2.0,2.2,
                  0.0, 0.2,0.4, 0.6,0.8,1.0,1.2,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,1.2,1.4,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,],
        'Salary': [6, 7, 7, 7,8,9,10,11,12,13,14,15,
                   3, 4, 4, 4,4,5,6,
                   2, 8,9,10,11,12,13,14,
                   1, 8,9,10,11,12,],
        'Children': ['Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'No','No', 'Yes', 'Yes', 'Yes', 'No',
                     'Yes', 'Yes', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 
                     'Yes', 'No','Yes', 'Yes', 'No','No', 'Yes','Yes',
                     'Yes', 'Yes', 'No','Yes', 'Yes','Yes',],
        'Days': [141, 123, 128, 66, 66, 120, 141, 52,96, 120, 141, 52,
                 141, 96, 120,120, 141, 52,96,
                 141,  15,123, 128, 66, 120, 141, 141,
                 141, 141,123, 128, 66,67,],
        }

#Convert to dataframe_1
df_1 = pd.DataFrame(data_set_1)
print("\n df_1 = \n",df_1)


#Create dataset_2
data_set_2 = {'id': [1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,
               2, 2, 2, 2, 2, 2, 2,
               3, 3, 3, 3, 3, 3, 3,3,
               4, 4, 4, 4, 4,4,],
        'cycle': [0.0, 0.2,0.4, 0.6, 0.8, 1,1.2,1.4,1.6,1.8,2.0,2.2,
                  0.0, 0.2,0.4, 0.6,0.8,1.0,1.2,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,1.2,1.4,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,],
        'Salary': [7, 8, 8, 8,8,9,14,21,12,19,14,20,
                   1, 6, 3, 8,4,9,8,
                   6, 4,9,10,4,12,13,6,
                   1, 4,9,10,9,4,],
        'Children': ['Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'No','No', 'Yes', 'Yes', 'Yes', 'No',
                     'Yes', 'Yes', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 
                     'Yes', 'No','Yes', 'Yes', 'No','No', 'Yes','Yes',
                     'Yes', 'Yes', 'No','Yes', 'Yes','Yes',],
        'Days': [141, 123, 128, 66, 66, 120, 141, 52,96, 120, 141, 52,
                 141, 96, 120,120, 141, 52,96,
                 141,  15,123, 128, 66, 120, 141, 141,
                 141, 141,123, 128, 66,67,],
        }

#Convert to dataframe_2
df_2 = pd.DataFrame(data_set_2)
print("\n df_2 = \n",df_2)

现在,我想在这里绘制cycleSalary,并在一个单独的图中为每个id重叠两个 Dataframe 。因此,我需要使用subplot函数如下:

## Plot for all id's
plt_fig_verify = plt.figure(figsize=(10,8))

## id1: 
plt.subplot(4,1,1)
plt.plot(df_1.groupby(by="id").get_group(1)['cycle'], df_1.groupby(by="id").get_group(1)['Salary'], 'b',  linewidth = '1', label ='id1: df_1')
plt.plot(df_2.groupby(by="id").get_group(1)['cycle'], df_2.groupby(by="id").get_group(1)['Salary'], 'r',  linewidth = '1', label ='id1: df_2')
plt.xlabel('cycle')
plt.ylabel('Salary')
plt.legend()

## id2: 
plt.subplot(4,1,2)
plt.plot(df_1.groupby(by="id").get_group(2)['cycle'], df_1.groupby(by="id").get_group(2)['Salary'], 'b',  linewidth = '1', label ='id2: df_1')
plt.plot(df_2.groupby(by="id").get_group(2)['cycle'], df_2.groupby(by="id").get_group(2)['Salary'], 'r',  linewidth = '1', label ='id2: df_2')
plt.xlabel('cycle')
plt.ylabel('Salary')
plt.legend()

## id3: 
plt.subplot(4,1,3)
plt.plot(df_1.groupby(by="id").get_group(3)['cycle'], df_1.groupby(by="id").get_group(3)['Salary'], 'b',  linewidth = '1', label ='id3: df_1')
plt.plot(df_2.groupby(by="id").get_group(3)['cycle'], df_2.groupby(by="id").get_group(3)['Salary'], 'r',  linewidth = '1', label ='id3: df_2')
plt.xlabel('cycle')
plt.ylabel('Salary')
plt.legend()

## id4: 
plt.subplot(4,1,4)
plt.plot(df_1.groupby(by="id").get_group(4)['cycle'], df_1.groupby(by="id").get_group(4)['Salary'], 'b',  linewidth = '1', label ='id4: df_1')
plt.plot(df_2.groupby(by="id").get_group(4)['cycle'], df_2.groupby(by="id").get_group(4)['Salary'], 'r',  linewidth = '1', label ='id4: df_2')
plt.xlabel('cycle')
plt.ylabel('Salary')
plt.legend()

plt.show()

结果如下所示:

但是,这里我需要编写子图函数的代码四次,即:对于 Dataframe 的所有四个ID,然后重叠。
有没有一种方法,我们可以有一些迭代函数,只写一次子图函数,并得到所有四个overalapped子图。
有人能告诉我如何在Python中实现这个任务吗?

wh6knrhe

wh6knrhe1#

我将concat两个 Dataframe ,然后使用一个groupby来制作子图:

colors = {"df_1": "blue", "df_2": "red"}
df = pd.concat([df_1, df_2], keys=colors)

fig, axs = plt.subplots(figsize=(10, 8), nrows=2, ncols=2)

for (n, g), ax in zip(df.groupby("id"), axs.flatten()):
    for s in df.index.levels[0]:
        g.loc[s].plot(
            x="cycle", y="Salary",
            xlabel="Cycle", ylabel="Salary",
            label=f"id {n}: {s}",
            color=colors[s],
            ax=ax
        )

plt.tight_layout()

plt.show();

输出:

如果你需要一个col,你可以这样更新subplots配置:

fig, axs = plt.subplots(figsize=(10, 8), nrows=len(df["id"].unique()))

wswtfjt7

wswtfjt72#

如果你想让这些图作为子图,并使用简短、干净和交互式的代码,我建议你使用Plotly!
你只需要执行pip install plotly,它的好处是pandas允许你使用plotly作为绘图的后端引擎!
在导入pandas import pandas as pd之后,您编写了这一小段代码pd.options.plotting.backend = "plotly"。仅此而已你可以使用Plotly!
我合并了你创建的两个 Dataframe ;我创建了一个名为source的列来区分第一个DataFrame的输入和第二个DataFrame的输入。
下面是修改后的代码示例:

#Load the required libraries
import pandas as pd
pd.options.plotting.backend = "plotly"

#Create dataset_1
data_set_1 = {'id': [1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,
               2, 2, 2, 2, 2, 2, 2,
               3, 3, 3, 3, 3, 3, 3,3,
               4, 4, 4, 4, 4,4,],
        'cycle': [0.0, 0.2,0.4, 0.6, 0.8, 1,1.2,1.4,1.6,1.8,2.0,2.2,
                  0.0, 0.2,0.4, 0.6,0.8,1.0,1.2,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,1.2,1.4,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,],
        'Salary': [6, 7, 7, 7,8,9,10,11,12,13,14,15,
                   3, 4, 4, 4,4,5,6,
                   2, 8,9,10,11,12,13,14,
                   1, 8,9,10,11,12,],
        'Children': ['Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'No','No', 'Yes', 'Yes', 'Yes', 'No',
                     'Yes', 'Yes', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 
                     'Yes', 'No','Yes', 'Yes', 'No','No', 'Yes','Yes',
                     'Yes', 'Yes', 'No','Yes', 'Yes','Yes',],
        'Days': [141, 123, 128, 66, 66, 120, 141, 52,96, 120, 141, 52,
                 141, 96, 120,120, 141, 52,96,
                 141,  15,123, 128, 66, 120, 141, 141,
                 141, 141,123, 128, 66,67,],
        }

#Create dataset_2
data_set_2 = {'id': [1, 1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,
               2, 2, 2, 2, 2, 2, 2,
               3, 3, 3, 3, 3, 3, 3,3,
               4, 4, 4, 4, 4,4,],
        'cycle': [0.0, 0.2,0.4, 0.6, 0.8, 1,1.2,1.4,1.6,1.8,2.0,2.2,
                  0.0, 0.2,0.4, 0.6,0.8,1.0,1.2,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,1.2,1.4,
                  0.0, 0.2,0.4, 0.6, 0.8,1.0,],
        'Salary': [7, 8, 8, 8,8,9,14,21,12,19,14,20,
                   1, 6, 3, 8,4,9,8,
                   6, 4,9,10,4,12,13,6,
                   1, 4,9,10,9,4,],
        'Children': ['Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'No','No', 'Yes', 'Yes', 'Yes', 'No',
                     'Yes', 'Yes', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 
                     'Yes', 'No','Yes', 'Yes', 'No','No', 'Yes','Yes',
                     'Yes', 'Yes', 'No','Yes', 'Yes','Yes',],
        'Days': [141, 123, 128, 66, 66, 120, 141, 52,96, 120, 141, 52,
                 141, 96, 120,120, 141, 52,96,
                 141,  15,123, 128, 66, 120, 141, 141,
                 141, 141,123, 128, 66,67,],
        }

#Convert to dataframe_1
df_1 = pd.DataFrame(data_set_1).assign(source='df_1')

#Convert to dataframe_2
df_2 = pd.DataFrame(data_set_2).assign(source='df_2')

(
    pd.concat([df_1, df_2])
    .plot.line(x='cycle', y='Salary', color='source', title='Salary by cycle', facet_row='id', markers=True)
)

你应该得到交互式子图,如下图所示:

我希望这对你有帮助!

相关问题