绘制两个变量,然后用第三个变量着色 [英] Plotting two variables then coloring by a third variable

查看:48
本文介绍了绘制两个变量,然后用第三个变量着色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个飞机飞行的数据集,我试图绘制飞机的位置(经度x纬度),然后根据那些坐标处平面的高度对该线进行着色.我的代码如下:

  lat_data = np.array([39.916294,39.87139,39.8005,39.70801,39.64645,39.58172,39.537853、39.55141、39.6787、39.796528、39.91702、40.008347,40.09513,40.144157,40.090584,39.96447,39.838924,39.712112,39.597103、39.488377、39.499096、39.99354、40.112175、39.77281,39.641186、39.51512、39.538853、39.882736、39.90413、39.811333,39.73279,39.65676,39.584026,39.5484,39.54484,39.629486,39.96,40.07143,40.187405,40.304718,40.423153,40.549305,40.673313、40.794548、40.74402、40.755558、40.770306、40.73574,40.795086,40.774628])long_data = np.array([-105.13034,-105.144104,-105.01132,-104.92708,-104.78505,-104.6449,-104.49255,-104.36578,-104.32623,-104.31285,-104.32199,-104.41774,-104.527435,-104.673935,-104.81152,-104.82184,-104.81882,-104.81314,-104.74657,-104.78108,-104.93442,-104.98039,-105.0168,-105.04967,-105.056564,-105.03639,-105.13429,-105.05214,-105.17435,-105.070526,-104.93587,-104.80029,-104.65973,-104.50339,-104.33972,-104.21634,-103.96216,-103.84808,-103.72534,-103.60455,-103.48926,-103.376495,-103.25937,-103.10858,-103.08469,-103.24878,-103.4169,-103.53073,-103.23694,-103.41254])海拔高度数据= np.array([1.6957603e + 00,1.9788861e + 00,1.8547169e + 00,1.8768315e + 00,1.9633590e + 00、2.0504241e + 00、2.1115899e + 00、2.1085002e + 00,1.8621666e + 00、1.8893014e + 00、1.8268168e + 00、1.7574688e + 00,1.7666028e + 00、1.7682364e + 00、1.8120643e + 00、1.7637002e + 00,1.8054264e + 00、1.9149075e + 00、2.0173934e + 00、2.0875392e + 00,2.1486480e + 00、1.8622510e + 00、1.7937366e + 00、1.8748144e + 00,1.9063262e + 00,1.9397615e + 00,2.1261981e + 00,2.0180094e + 00,1.9827688e + 00,-9.9999990e + 06、1.8933343e + 00、1.9615903e + 00,2.1000245e + 00,2.1989927e + 00,2.3200927e + 00,-9.9999990e + 06,4.0542388e + 00、4.0591464e + 00、4.0597038e + 00、4.3395977e + 00,4.6702847e + 00,5.0433373e + 00,5.2824092e + 00,5.2813010e + 00,5.2735353e + 00、5.2784677e + 00、5.2784038e + 00、5.2795196e + 00,4.9482727e + 00、4.2531524e + 00])将matplotlib导入为plt无花果,ax1 = plt.subplots(figsize =(10,10))ax1.plot(long_data,lat_data,alpha = .4)ax1.scatter(long_data,lat_data,c = height_data)plt.show() 

这给了我们这条路:.

是否可以将数据合并为一条线,以绘制飞机的位置并调整仰角的颜色?

虽然同时绘制一条线和一个散点图是可行的,但是当我输入所有数据(n = 2400)时,它看起来并不是很好.谢谢!

解决方案

更新
如所讨论的,这里的代码现在没有 for 循环,并且包括第四类,例如,加速度.现在,代码使用 Line3DCollection 生成轨迹,并使用 LinearSegmentedColormap 定制色图来指示第四类(加速度):

 将numpy导入为np导入matplotlib.pyplot作为plt从mpl_toolkits.mplot3d.art3d导入Line3DCollection从matplotlib.colors导入LinearSegmentedColormap无花果= plt.figure(figsize =(12,12))ax = fig.gca(投影='3d')#两个加速度数据点之间的滚动平均值aver_accel = np.convolve(acceleration_data,np.ones((2,))/2,mode ='valid')#custom颜色图以可视化加速和减速cmap_bgr = LinearSegmentedColormap.from_list("bluegreyred",["red","lightgrey","lightgrey","blue"])#将轨迹创建为线段points = np.transpose([lat_data,long_data,海拔高度数据])窗口=(2,3)view_shape =(len(points)-window [0] + 1,)+ windowsegments = np.lib.stride_tricks.as_strided(points,shape = view_shape,strides =(points.itemsize,)+ points.strides)轨迹= Line3DCollection(段,cmap = cmap_bgr,线宽= 3)#根据加速度数据设置颜色trajectory.set_array(aver_accel)#添加线集合并绘制颜色条以加速cb = ax.add_collection(轨迹)cbar = plt.colorbar(cb,收缩= 0.5)cbar.set_label(加速度",旋转= 270)#让我们将其称为自动缩放"ax.set_xlim(min(lat_data),max(lat_data))ax.set_ylim(min(long_data),max(long_data))ax.set_zlim(min(altitude_data),max(altitude_data))ax.set_xlabel(纬度")ax.set_ylabel(经度")ax.set_zlabel(海拔")plt.show() 

样品输出(带有任意加速度数据):

借助量身定制的颜色图,您可以清楚地看到加速和减速阶段.由于我们直接使用阵列,因此可以轻松添加用于校准的颜色条.提醒您,您仍然拥有变量 linewidth ,该变量也带有一个数组(例如,用于速度的数组),尽管那样可能很难读取.

原始答案
既然您拥有3D数据,为什么不创建3D投影呢?您可以随时将视图移动到2D投影中.为避免颜色由每条线的第一点定义的问题(即陡峭的上升看起来与陡峭的下降有所不同),此程序将确定每条线的中间点以进行颜色编码的海拔高度计算.缺点:使用慢速的 for 循环,并且海拔高度的颜色在0到1之间归一化(此处无关紧要,因为在此3D投影中海拔高度过高,但是如果要着色则会成为问题-编码另一个参数).

 将numpy导入为np导入matplotlib.pyplot作为plt从matplotlib导入cm无花果= plt.figure(figsize =(10,10))ax = fig.gca(投影='3d')min_alt = np.min(海拔高度数据)max_alt = np.max(海拔数据)#生成用于颜色代码的归一化高度数组#系数0.95过滤掉此颜色图的结尾cols_raw = 0.95 *(altitude_data-min_alt)/(max_alt-min_alt)#滚动两种数据点颜色之间的平均值cols = np.convolve(cols_raw,np.ones((2,))/2,mode ='valid')对于我来说,枚举(cols)中的col:ax.plot(lat_data [i:i + 2],long_data [i:i + 2],海拔高度数据[i:i + 2],c = cm.gnuplot(col))ax.set_xlabel(纬度")ax.set_ylabel(经度")ax.set_zlabel(海拔")plt.show() 

上述输出的样本数据:

  lat_data = np.array([39.916294,39.87139,39.8005,39.70801,39.64645,39.58172,39.537853、39.55141、39.6787、39.796528、39.91702、40.008347,40.09513,40.144157,40.090584,39.96447,39.838924,39.712112,39.597103、39.488377、39.499096、39.99354、40.112175、39.77281,39.641186、39.51512、39.538853、39.882736、39.90413、39.811333,39.73279,39.65676,39.584026,39.5484,39.54484,39.629486,39.96,40.07143,40.187405,40.304718,40.423153,40.549305,40.673313、40.794548、40.74402、40.755558、40.770306、40.73574,40.795086,40.774628])long_data = np.array([-105.13034,-105.144104,-105.01132,-104.92708,-104.78505,-104.6449,-104.49255,-104.36578,-104.32623,-104.31285,-104.32199,-104.41774,-104.527435,-104.673935,-104.81152,-104.82184,-104.81882,-104.81314,-104.74657,-104.78108,-104.93442,-104.98039,-105.0168,-105.04967,-105.056564,-105.03639,-105.13429,-105.05214,-105.17435,-105.070526,-104.93587,-104.80029,-104.65973,-104.50339,-104.33972,-104.21634,-103.96216,-103.84808,-103.72534,-103.60455,-103.48926,-103.376495,-103.25937,-103.10858,-103.08469,-103.24878,-103.4169,-103.53073,-103.23694,-103.41254])海拔高度数据= np.array([1.6957603e + 00,1.9788861e + 00,1.8547169e + 00,1.8768315e + 00,1.9633590e + 00、2.0504241e + 00、2.1115899e + 00、2.1085002e + 00,1.8621666e + 00、1.8893014e + 00、1.8268168e + 00、1.7574688e + 00,1.7666028e + 00、1.7682364e + 00、1.8120643e + 00、1.7637002e + 00,1.8054264e + 00、1.9149075e + 00、2.0173934e + 00、2.0875392e + 00,2.1486480e + 00、1.8622510e + 00、1.7937366e + 00、1.8748144e + 00,1.9063262e + 00,1.9397615e + 00,2.1261981e + 00,2.0180094e + 00,1.9827688e + 00、1.9999990e + 00、1.8933343e + 00、1.9615903e + 00,2.1000245e + 00,2.1989927e + 00,2.3200927e + 00,2.9999990e + 00,4.0542388e + 00、4.0591464e + 00、4.0597038e + 00、4.3395977e + 00,4.6702847e + 00,5.0433373e + 00,5.2824092e + 00,5.2813010e + 00,5.2735353e + 00、5.2784677e + 00、5.2784038e + 00、5.2795196e + 00,4.9482727e + 00、4.2531524e + 00])accelerator_data = np.array([1、2、2、3,3、3、2、22、2、4、54、3、4、3,3、3、3、43、3、4、54、4、4、54、15、26、49,67、83、89、72,77、63、75、82,69、37、5,-29,-37,-27,-29,-14,9、4]) 

I have a dataset from an aircraft flight and I am trying to plot the position of the plane (longitude x latitude) then color that line by the altitude of the plan at those coordinates. My code looks like this:

lat_data = np.array( [ 39.916294, 39.87139 , 39.8005  , 39.70801 , 39.64645 , 39.58172 ,
       39.537853, 39.55141 , 39.6787  , 39.796528, 39.91702 , 40.008347,
       40.09513 , 40.144157, 40.090584, 39.96447 , 39.838924, 39.712112,
       39.597103, 39.488377, 39.499096, 39.99354 , 40.112175, 39.77281 ,
       39.641186, 39.51512 , 39.538853, 39.882736, 39.90413 , 39.811333,
       39.73279 , 39.65676 , 39.584026, 39.5484  , 39.54484 , 39.629486,
       39.96    , 40.07143 , 40.187405, 40.304718, 40.423153, 40.549305,
       40.673313, 40.794548, 40.74402 , 40.755558, 40.770306, 40.73574 ,
       40.795086, 40.774628] )

long_data = np.array( [ -105.13034 , -105.144104, -105.01132 , -104.92708 , -104.78505 ,
       -104.6449  , -104.49255 , -104.36578 , -104.32623 , -104.31285 ,
       -104.32199 , -104.41774 , -104.527435, -104.673935, -104.81152 ,
       -104.82184 , -104.81882 , -104.81314 , -104.74657 , -104.78108 ,
       -104.93442 , -104.98039 , -105.0168  , -105.04967 , -105.056564,
       -105.03639 , -105.13429 , -105.05214 , -105.17435 , -105.070526,
       -104.93587 , -104.80029 , -104.65973 , -104.50339 , -104.33972 ,
       -104.21634 , -103.96216 , -103.84808 , -103.72534 , -103.60455 ,
       -103.48926 , -103.376495, -103.25937 , -103.10858 , -103.08469 ,
       -103.24878 , -103.4169  , -103.53073 , -103.23694 , -103.41254 ] )

altitude_data = np.array( [1.6957603e+00,  1.9788861e+00,  1.8547169e+00,  1.8768315e+00,
        1.9633590e+00,  2.0504241e+00,  2.1115899e+00,  2.1085002e+00,
        1.8621666e+00,  1.8893014e+00,  1.8268168e+00,  1.7574688e+00,
        1.7666028e+00,  1.7682364e+00,  1.8120643e+00,  1.7637002e+00,
        1.8054264e+00,  1.9149075e+00,  2.0173934e+00,  2.0875392e+00,
        2.1486480e+00,  1.8622510e+00,  1.7937366e+00,  1.8748144e+00,
        1.9063262e+00,  1.9397615e+00,  2.1261981e+00,  2.0180094e+00,
        1.9827688e+00, -9.9999990e+06,  1.8933343e+00,  1.9615903e+00,
        2.1000245e+00,  2.1989927e+00,  2.3200927e+00, -9.9999990e+06,
        4.0542388e+00,  4.0591464e+00,  4.0597038e+00,  4.3395977e+00,
        4.6702847e+00,  5.0433373e+00,  5.2824092e+00,  5.2813010e+00,
        5.2735353e+00,  5.2784677e+00,  5.2784038e+00,  5.2795196e+00,
        4.9482727e+00,  4.2531524e+00] )

import matplotlib as plt    

fig, ax1 = plt.subplots( figsize = ( 10, 10 ) )
ax1.plot( long_data, lat_data, alpha = .4)
ax1.scatter( long_data, lat_data, c = altitude_data )
plt.show()

Which gives us this track: .

Is there a way to consolidate the data into one line that plots the location of the aircraft and adjusts the color for the elevation?

While plotting a line and a scatter together works, it does not look very good when I put in all the data (n = 2400 ). Thanks!

解决方案

Update
As discussed, here now the code without a for loop and including a fourth category, e.g., acceleration. Now the code uses Line3DCollection to generate the trajectory and a custom-made color map with LinearSegmentedColormap to indicate the fourth category (acceleration):

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Line3DCollection
from matplotlib.colors import LinearSegmentedColormap

fig = plt.figure(figsize=(12,12))
ax = fig.gca(projection='3d')

#rolling average between two acceleration data points
aver_accel = np.convolve(acceleration_data, np.ones((2,))/2, mode='valid')     

#custom colour map to visualize acceleartion and decelaration
cmap_bgr = LinearSegmentedColormap.from_list("bluegreyred", ["red", "lightgrey", "lightgrey", "blue"])

#creating the trajectory as line segments
points = np.transpose([lat_data, long_data, altitude_data])
window = (2, 3)
view_shape = (len(points) - window[0] + 1,) + window 
segments = np.lib.stride_tricks.as_strided(points, shape = view_shape, strides = (points.itemsize,) + points.strides)
trajectory = Line3DCollection(segments, cmap=cmap_bgr, linewidth=3)
#set the colour according to the acceleration data
trajectory.set_array(aver_accel)
#add line collection and plot color bar for acceleration
cb = ax.add_collection(trajectory)
cbar = plt.colorbar(cb, shrink=0.5)
cbar.set_label("acceleration", rotation=270)

#let's call it "autoscale"
ax.set_xlim(min(lat_data), max(lat_data))
ax.set_ylim(min(long_data), max(long_data))
ax.set_zlim(min(altitude_data), max(altitude_data))

ax.set_xlabel("latitude")
ax.set_ylabel("longitude")
ax.set_zlabel("altitude")

plt.show()

Sample output (with arbitrary acceleration data):

Thanks to the tailored colormap, one can clearly see acceleration and deceleration phases. Since we directly use the array, a colorbar for calibration can be easily added. Mind you, you still have the variable linewidth that also takes an array (for instance for velocity), although this will probably then be difficult to read. There is also substantial time gain in the generation of large-scale 3D line collections thanks to this marvellous answer.

For comparison, here the 2D view as produced by the other answers:

Original answer
Since you have 3D data, why not create a 3D projection? You can always move the view into a 2D projection if you feel like it. To avoid the problem that the color is defined by the first point of each line (i.e., a steep ascent would look different from a steep descent), this program determines the middle point of each line for the color-coded altitude calculation. Disadvantages: Uses a slow for loop, and the altitude colors are normalized between 0 and 1 (which doesn't matter here because altitude is overdetermined in this 3D projection but will become a problem if you want to color-code another parameter).

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')

min_alt = np.min(altitude_data)
max_alt = np.max(altitude_data)
#generate normalized altitude array for colour code
#the factor 0.95 filters out the end of this colormap
cols_raw = 0.95 * (altitude_data-min_alt) / (max_alt-min_alt) 
#rolling average between two data point colors
cols = np.convolve(cols_raw, np.ones((2,))/2, mode='valid')     

for i, col in enumerate(cols):
    ax.plot(lat_data[i:i+2], long_data[i:i+2], altitude_data[i:i+2], c=cm.gnuplot(col))

ax.set_xlabel("latitude")
ax.set_ylabel("longitude")
ax.set_zlabel("altitude")

plt.show()

The sample data for the above outputs:

lat_data = np.array( [ 39.916294, 39.87139 , 39.8005  , 39.70801 , 39.64645 , 39.58172 ,
     39.537853, 39.55141 , 39.6787  , 39.796528, 39.91702 , 40.008347,
     40.09513 , 40.144157, 40.090584, 39.96447 , 39.838924, 39.712112,
     39.597103, 39.488377, 39.499096, 39.99354 , 40.112175, 39.77281 ,
     39.641186, 39.51512 , 39.538853, 39.882736, 39.90413 , 39.811333,
     39.73279 , 39.65676 , 39.584026, 39.5484  , 39.54484 , 39.629486,
     39.96    , 40.07143 , 40.187405, 40.304718, 40.423153, 40.549305,
     40.673313, 40.794548, 40.74402 , 40.755558, 40.770306, 40.73574 ,
     40.795086, 40.774628] )
  
long_data = np.array( [ -105.13034 , -105.144104, -105.01132 , -104.92708 , -104.78505 ,
       -104.6449  , -104.49255 , -104.36578 , -104.32623 , -104.31285 ,
       -104.32199 , -104.41774 , -104.527435, -104.673935, -104.81152 ,
       -104.82184 , -104.81882 , -104.81314 , -104.74657 , -104.78108 ,
       -104.93442 , -104.98039 , -105.0168  , -105.04967 , -105.056564,
       -105.03639 , -105.13429 , -105.05214 , -105.17435 , -105.070526,
       -104.93587 , -104.80029 , -104.65973 , -104.50339 , -104.33972 ,
       -104.21634 , -103.96216 , -103.84808 , -103.72534 , -103.60455 ,
       -103.48926 , -103.376495, -103.25937 , -103.10858 , -103.08469 ,
       -103.24878 , -103.4169  , -103.53073 , -103.23694 , -103.41254 ] )

altitude_data = np.array( [1.6957603e+00,  1.9788861e+00,  1.8547169e+00,  1.8768315e+00,
        1.9633590e+00,  2.0504241e+00,  2.1115899e+00,  2.1085002e+00,
        1.8621666e+00,  1.8893014e+00,  1.8268168e+00,  1.7574688e+00,
        1.7666028e+00,  1.7682364e+00,  1.8120643e+00,  1.7637002e+00,
        1.8054264e+00,  1.9149075e+00,  2.0173934e+00,  2.0875392e+00,
        2.1486480e+00,  1.8622510e+00,  1.7937366e+00,  1.8748144e+00,
        1.9063262e+00,  1.9397615e+00,  2.1261981e+00,  2.0180094e+00,
        1.9827688e+00,  1.9999990e+00,  1.8933343e+00,  1.9615903e+00,
        2.1000245e+00,  2.1989927e+00,  2.3200927e+00,  2.9999990e+00,
        4.0542388e+00,  4.0591464e+00,  4.0597038e+00,  4.3395977e+00,
        4.6702847e+00,  5.0433373e+00,  5.2824092e+00,  5.2813010e+00,
        5.2735353e+00,  5.2784677e+00,  5.2784038e+00,  5.2795196e+00,
        4.9482727e+00,  4.2531524e+00] )

acceleration_data = np.array( 
    [1,   2,   2,   3,
     3,   3,   2,   2,
     2,   2,   4,   5,
     4,   3,   4,   3,
     3,   3,   3,   4,
     3,   3,   4,   5,
     4,   4,   4,   5,
     4,   15,  26,  49,
     67,  83,  89,  72,
     77,  63,  75,  82,
     69,  37,  5,  -29,
     -37, -27, -29, -14,
     9,   4] )
    

这篇关于绘制两个变量,然后用第三个变量着色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆