【问题标题】:How can I produce a 3D space-time trajectory plot?如何生成 3D 时空轨迹图?
【发布时间】:2017-12-13 18:17:21
【问题描述】:

假设我有 3 个数据框,其中包含有关对象的纬度、经度和时间标签的信息,这样每一列代表一个不同的对象,每一行代表一个时间点。

latitudes =
object          1            2            3                
0          -8.064267    -8.047483    -8.056339       
1          -8.064267    -8.047483    -8.056339     
2          -8.064267    -8.047483    -8.056339   
3          -8.064267    -8.047483    -8.056339   
4          -8.064267    -8.047483    -8.056339   
5          -8.064267    -8.047483    -8.056339   


longitudes =
object          1            2            3         
0         -34.878386   -34.904086   -34.889661     
1         -34.878386   -34.904086   -34.889661     
2         -34.878386   -34.904086   -34.889661    
3         -34.878386   -34.904086   -34.889661   
4         -34.878386   -34.904086   -34.889661    
5         -34.878386   -34.904086   -34.889661   

times =
object  1                      2                     3                   
0       2016-03-05 07:52:00   2016-03-05 16:26:00   2016-03-05 16:58:00   
1       2016-03-05 08:19:00   2016-03-05 16:42:00   2016-03-05 17:45:00   
2       2016-03-05 08:52:00   2016-03-05 17:06:00   2016-03-05 17:58:00   
3       2016-03-05 09:36:00   2016-03-05 18:21:00   2016-03-05 18:23:00   
4           NaT               2016-03-05 23:06:00   2016-03-05 22:38:00   
5           NaT               2016-03-05 23:09:00       NaT  

我想绘制一个 3D 轨迹,时间在 z 轴上,经度在 x 轴上,纬度在 y 轴上,所有物体的轨迹都在同一个图上。我该怎么做?

这是我的尝试,但它不起作用:

    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(111,projection='3d')
ax.plot(longitudes.values,latitudes.values,times.values)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('Time')
    plt.show()

错误:

ValueError: third arg must be a format string

谢谢

【问题讨论】:

  • 对于二维绘图,第三个参数保留给标记类型,使用字符串指定。我认为您收到了默认错误消息,因为数组 times.values 不被理解。这个数组的类型是什么?它看起来像日期时间或类似的东西。您是否尝试在调用 plot 之前将其转换为浮点数?
  • 它实际上是一个对象,因为除了日期时间值之外还有一些 NaT。
  • 我建议您提供问题的minimal reproducible example,可以复制并运行以重现错误。否则,解决方案将需要做出假设,这可能对您的情况有效,也可能无效。
  • @ImportanceOfBeingErnest 我编辑了问题并在“times”数据框中添加了“NaT”值,所以它应该是 MCV。
  • 不,这不是minimal reproducible example,我花了很长时间才重现这个问题。请参阅我的回答,了解 minimal reproducible example 的外观 - 它可以被复制和运行。

标签: python python-3.x pandas matplotlib mplot3d


【解决方案1】:
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('Time')

for t in times.columns:
    ax.plot(longitudes[t].values, latitudes[t].values, times[t].values, label='t')

ax.legend()

Lm.png

【讨论】:

  • 感谢您的回答。我仍然得到同样的错误。我的时间数据框是日期时间类型。你是怎么转换的?
  • 我在某些时间值中也有“NaT”,因为对象不一定具有相同数量的时间点,所以这可能是错误的原因。身份证
【解决方案2】:

您需要过滤掉 NaT 值,因为它们无法被绘制出来。

latitudes = u"""                
-8.064267    -8.047483    -8.056339       
-8.064267    -8.047483    -8.056339     
-8.064267    -8.047483    -8.056339   
-8.064267    -8.047483    -8.056339   
-8.064267    -8.047483    -8.056339   
-8.064267    -8.047483    -8.056339"""  


longitudes = u"""        
-34.878386   -34.904086   -34.889661     
-34.878386   -34.904086   -34.889661     
-34.878386   -34.904086   -34.889661    
-34.878386   -34.904086   -34.889661   
-34.878386   -34.904086   -34.889661    
-34.878386   -34.904086   -34.889661""" 

times = u"""                
2016-03-05 07:52:00, 2016-03-05 16:26:00, 2016-03-05 16:58:00   
2016-03-05 08:19:00, 2016-03-05 16:42:00, 2016-03-05 17:45:00   
2016-03-05 08:52:00, 2016-03-05 17:06:00, 2016-03-05 17:58:00   
2016-03-05 09:36:00, 2016-03-05 18:21:00, 2016-03-05 18:23:00   
2016-03-05 09:36:00, 2016-03-05 23:06:00, 2016-03-05 22:38:00   
2016-03-05 09:36:00, 2016-03-05 23:09:00, 2016-03-05 09:36:00
"""

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

kw = dict(delim_whitespace=True, header=None)
latitudes = pd.read_csv(io.StringIO(latitudes),**kw)
longitudes = pd.read_csv(io.StringIO(longitudes),**kw)
times = pd.read_csv(io.StringIO(times), delimiter=",",
                    infer_datetime_format=True,header=None)
times.iloc[4:,0] = None
times.iloc[5,2] = None

for i in times.columns:
    times[i] = pd.to_datetime(times[i], format="%Y-%m-%d %H:%M:%S")

fig = plt.figure()
ax = fig.add_subplot(111,projection='3d')

for t in times.columns:
    inx = times[t].values != None
    x = longitudes[t].values[inx]
    y = latitudes[t].values[inx]
    z = times[t].values[inx]
    ax.plot(x,y,z)

ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('Time')
plt.show()

【讨论】:

  • 我试过你的方法。此行仍然没有过滤 NaT 值:inx = times[t].values != None
  • 好吧,我只能告诉你,它确实有效,如上述答案所示。您可能决定最终提供该问题的minimal reproducible example,以使错误可重现。
猜你喜欢
  • 1970-01-01
  • 2020-05-07
  • 1970-01-01
  • 2018-01-08
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
相关资源
最近更新 更多