pandas 多个数据帧的 3D 图

pandas 3D plot for multiple dataframes

我的目标是绘制类似于以下 link.

顶部图表的内容

我有好几个txt文件,每个文件对应一个不同的样本。 目前,我将我的数据加载为 pandas 数据帧(尽管我不确定如果我加载为 numpy 数组是否会更容易):

sample4.head()
Out[61]: 
           20       40       60       80      100
x                                                
1.10  1.09734  1.25772  1.41810  1.57847  1.73885
1.11  1.06237  1.21307  1.36378  1.51448  1.66518
1.12  1.02176  1.16346  1.30516  1.44686  1.58856
1.13  0.97769  1.11097  1.24426  1.37754  1.51083
1.14  0.93162  1.05702  1.18241  1.30781  1.43321

test5.head()
Out[62]: 
           20       40       60       80      100
x                                                
1.10  1.12427  1.31545  1.50663  1.69781  1.88899
1.11  1.06327  1.24045  1.41763  1.59482  1.77200
1.12  0.99875  1.16302  1.32730  1.49158  1.65585
1.13  0.93276  1.08509  1.23742  1.38975  1.54208
1.14  0.86668  1.00792  1.14916  1.29040  1.43164

test6.head()
Out[63]: 
           20       40       60       80      100
x                                                
1.10  1.08463  1.30038  1.51612  1.73187  1.94761
1.11  0.99905  1.19626  1.39346  1.59067  1.78788
1.12  0.91255  1.09283  1.27310  1.45337  1.63365
1.13  0.82706  0.99181  1.15656  1.32131  1.48605
1.14  0.74381  0.89429  1.04477  1.19525  1.34572

可以看出,所有样本共享一列。以下方法适用于单个样本,给出一个简单的二维图:

sample4.plot()

但我的想法是沿着 y 轴绘制我拥有的所有数据帧,这意味着 y 轴应该是我拥有的每个单独样本,在 3d 图中,如上例,但我不知道如何 "stack" 数据帧并使用第三轴绘制它们。

如有任何帮助,我们将不胜感激。

提前致谢。

这是一种方法,使用 melt and Axes3D

首先生成OP提供的示例数据:

import pandas as pd
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

sample4_z = [1.09734,  1.25772,  1.4181 ,  1.57847,  1.73885,  1.06237,
             1.21307,  1.36378,  1.51448,  1.66518,  1.02176,  1.16346,
             1.30516,  1.44686,  1.58856,  0.97769,  1.11097,  1.24426,
             1.37754,  1.51083,  0.93162,  1.05702,  1.18241,  1.30781,  
             1.43321]

test5_z = [1.12427,  1.31545,  1.50663,  1.69781,  1.88899,  1.06327,
           1.24045,  1.41763,  1.59482,  1.772  ,  0.99875,  1.16302,
           1.3273 ,  1.49158,  1.65585,  0.93276,  1.08509,  1.23742,
           1.38975,  1.54208,  0.86668,  1.00792,  1.14916,  1.2904 , 
           1.43164]

test6_z = [1.08463,  1.30038,  1.51612,  1.73187,  1.94761,  0.99905,
           1.19626,  1.39346,  1.59067,  1.78788,  0.91255,  1.09283,
           1.2731 ,  1.45337,  1.63365,  0.82706,  0.99181,  1.15656,
           1.32131,  1.48605,  0.74381,  0.89429,  1.04477,  1.19525,  
           1.34572]

def make_df(data):
    x = [1.1, 1.11, 1.12, 1.13, 1.14]
    y = [20, 40, 60, 80, 100]
    z = np.array(data).reshape((len(x),len(y)))
    return pd.DataFrame(z, index=x, columns=y).reset_index().rename(columns={'index':'x'})

sample4 = make_df(sample4_z)
test5 = make_df(test5_z)
test6 = make_df(test6_z)

现在在一个 3D 网格上绘制所有三个数据框:

# signal to pyplot that we want 3d plots
fig, ax = plt.subplots(1, 1, figsize=(10, 10), subplot_kw={'projection': '3d'})

# convenience wrapper for plotting function
def plot_3d(df):
    ax.plot(df.x, df.y.astype(float), df.z) # dims must be floats

# reshape with melt(), then plot
plot_3d(pd.melt(sample4, id_vars='x', var_name='y', value_name='z'))
plot_3d(pd.melt(test5, id_vars='x', var_name='y', value_name='z'))
plot_3d(pd.melt(test6, id_vars='x', var_name='y', value_name='z'))

# label axes
ax.set_xlabel('x', fontsize=20)
ax.set_ylabel('y', fontsize=20)
ax.set_zlabel('z', fontsize=20)

# optional view configurations
ax.elev = 10
ax.axim = 20

更新 回复:y 轴分类
只有两个连续值轴,通常没有必要(也不推荐)调用 3D 绘图表面(参见,例如,this similar discussion)。将分类变量编码为带标签的维度会更清楚。

这种情况因代表第四维的样本组级别而变得更加复杂。我建议考虑一组图,其中 y 轴类别编码为图例。像这样:

datasets = ['sample4','test5','test6']
line_types = ['-.','--','-']
fix, axes = plt.subplots(1,3, figsize=(14,5))
for i, data in enumerate([sample4, test5, test6]):
    data.set_index('x').plot(style=line_types[i], ax=axes[i], sharey=True, 
                             xticks=data.x, title=datasets[i])

不过,如果您真的想保持 3D 效果,具有正确视图旋转的散点图将为您提供所需的效果。这也避免了 y 轴被读取为度量变量而不是顺序变量的问题。

# scatter plot with categorical y-axis
def plot_3d(df, color):
    ax.scatter(df.x, df.y, df.z, c=color) # dims must be floats

# reshape with melt(), then plot
plot_3d(pd.melt(sample4, id_vars='x', var_name='y', value_name='z'), 'red')
plot_3d(pd.melt(test5, id_vars='x', var_name='y', value_name='z'), 'blue')
plot_3d(pd.melt(test6, id_vars='x', var_name='y', value_name='z'), 'green')

# label axes
ax.set_xlabel('x', fontsize=20)
ax.set_ylabel('y', fontsize=20)
ax.set_zlabel('z', fontsize=20)

# optional view configurations
ax.elev = 10
ax.azim = 280

注意:可以使用 bar3d class 将一个或多个维度视为分类,但其对具有相同类别值的多个点的级联方法可能无法满足您的需求正在寻找。