2017-05-20 26 views
3

我有一个由x,y和z列给出非均匀间隔数据点的pandas DataFrame,其中x和y是变量对,z是因变量。例如:matplotlib轮廓到数据区域的限制/遮罩

import matplotlib.pyplot as plt 
from matploblib.mlab import griddata 
import numpy as np 
import pandas as pd 

df = pd.DataFrame({'x':[0, 0, 1, 1, 3, 3, 3, 4, 4, 4], 
        'y':[0, 1, 0, 1, 0.2, 0.7, 1.4, 0.2, 1.4, 2], 
        'z':[50, 40, 40, 30, 30, 30, 20, 20, 20, 10]}) 

x = df['x'] 
y = df['y'] 
z = df['z'] 

我想在x和y上做因变量z的等高线图。为此,我创建了一个新的网格来插入使用matplotlib.mlab的griddata函数的数据。

xi = np.linspace(x.min(), x.max(), 100) 
yi = np.linspace(y.min(), y.max(), 100) 
z_grid = griddata(x, y, z, xi, yi, interp='linear') 
plt.contourf(xi, yi, z_grid, 15) 
plt.scatter(x, y, color='k') # The original data points 
plt.show() 

虽然这个工作,输出是不是我想要的。我不希望griddata插入到由x和y数据的最小值和最大值给出的边界之外。下面的图是调用plt.show()后显示的内容,然后用紫色突出显示了我想插入和绘制轮廓的数据区域。紫色线外的轮廓应该是空白的。我怎么能隐瞒边缘数据呢?

Plot as created by mplPlot as it should be

linked question不可惜没有回答我的问题,因为我没有一个明确的数学方法来定义上做三角测量的条件。是否可以根据数据单独定义一个条件来屏蔽数据,以上面的Dataframe为例?

+0

链接的问题不可惜没有回答我的问题,因为我没有一个明确的数学方法来定义上做三角测量的条件。是否可以根据数据单独定义一个条件来屏蔽数据,以上面的Dataframe为例? – Alarik

+0

我解释了你的“最小和最大”,让你有一个条件。如果情况并非如此,请参阅下面的答案。 – ImportanceOfBeingErnest

回答

3

正如this question的答案所示,可能会引入一个条件来掩盖这些值。

来自问题的句子 “我不希望griddata插入到由x和y数据的最小值和最大值给出的边界之外。”意味着存在一些可以使用的最小/最大条件。

如果不是这种情况,可以使用路径剪切轮廓。由于没有通用的方法来知道哪些点应该是边缘,因此需要指定此路径的点。下面的代码为三种不同的可能路径做了这个。

import matplotlib.pyplot as plt 
from matplotlib.path import Path 
from matplotlib.patches import PathPatch 
from matplotlib.mlab import griddata 
import numpy as np 
import pandas as pd 

df = pd.DataFrame({'x':[0, 0, 1, 1, 3, 3, 3, 4, 4, 4], 
        'y':[0, 1, 0, 1, 0.2, 0.7, 1.4, 0.2, 1.4, 2], 
        'z':[50, 40, 40, 30, 30, 30, 20, 20, 20, 10]}) 

x = df['x'] 
y = df['y'] 
z = df['z'] 

xi = np.linspace(x.min(), x.max(), 100) 
yi = np.linspace(y.min(), y.max(), 100) 
z_grid = griddata(x, y, z, xi, yi, interp='linear') 

clipindex = [ [0,2,4,7,8,9,6,3,1,0], 
       [0,2,4,7,5,8,9,6,3,1,0], 
       [0,2,4,7,8,9,6,5,3,1,0]] 

fig, axes = plt.subplots(ncols=3, sharey=True) 
for i, ax in enumerate(axes): 
    cont = ax.contourf(xi, yi, z_grid, 15) 
    ax.scatter(x, y, color='k') # The original data points 
    ax.plot(x[clipindex[i]], y[clipindex[i]], color="crimson") 

    clippath = Path(np.c_[x[clipindex[i]], y[clipindex[i]]]) 
    patch = PathPatch(clippath, facecolor='none') 
    ax.add_patch(patch) 
    for c in cont.collections: 
     c.set_clip_path(patch) 

plt.show() 

enter image description here

+0

如果问题不明确,我很抱歉。这种解决方案正是我需要的那种数据。 – Alarik