【问题标题】:How to plot timedelta data from a pandas DataFrame?如何从 pandas DataFrame 中绘制 timedelta 数据?
【发布时间】:2018-02-04 03:34:00
【问题描述】:

我正在尝试绘制一个系列(准确地说是数据框中的列)。它似乎具有 hh:mm:ss (timedelta64) 格式的有效数据

In [14]: x5.task_a.describe()
Out[14]: 
count                       165
mean     0 days 03:35:41.121212
std      0 days 07:07:40.950819
min             0 days 00:00:06
25%             0 days 00:37:13
50%             0 days 01:28:17
75%             0 days 03:41:32
max             2 days 12:32:26
Name: task_a, dtype: object

In [15]: x5.task_a.head()
Out[15]: 
wbdqueue_id
26868   00:26:11
26869   02:08:28
26872   00:26:07
26874   00:48:22
26875   00:26:17
Name: task_a, dtype: timedelta64[ns]

但是当我尝试绘制它时,我收到一条错误消息,指出空的“DataFrame”中没有数字数据。 我试过了: x5.task_a.plot.kde() 和 x5.plot() 其中 x5 是具有多个此类 timedelta 数据系列的 DataFrame。

TypeError: Empty 'DataFrame': no numeric data to plot

我发现可以生成一系列随机值并将其绘制出来。

我做错了什么?

【问题讨论】:

  • Pandas 无法绘制非数字数据。 x5.task_a 列不是 timedelta,而是一个字符串(否则,x5.task_a.describe() 会将其报告为 timedelta64,而不是 object)。解决方法是将列转换为日期时间格式。
  • @DYZ,我相信它在 timedelta 中有两个原因:(1)当我尝试将其更改为 datetime 时(x.task_a=x5.task_a.apply(pd.datetime) 我明白了错误:TypeError: is not convertible to datetime and (2) x5.task_a.head(), above, 表明内容是 timedelta64 类型的。
  • @DYZ 我遇到了同样的错误,而且我的也是 pandas timedelta:当我查看 print(joyData.timeTaken.dtype) 时,我得到了 timedelta64[ns]
  • 仅供参考:有一个github issue 关于这个。
  • 试试(x5.task_a / np.timedelta64(1, 'h')).plot.kde()?

标签: python pandas plot


【解决方案1】:

转换为任何逻辑数值,例如小时或分钟,然后使用.plot.kde()

(x5.task_a / np.timedelta64(1, 'h')).plot.kde()

详情

In [149]: x5
Out[149]:
                  task_a
0 0 days 22:27:46.684800
1 1 days 00:20:43.036800
2 0 days 12:16:24.873600
3 1 days 11:10:14.880000
4 1 days 03:31:05.548800
5 1 days 05:20:52.944000
6 1 days 00:09:09.590400
7 0 days 13:53:50.179200
8 1 days 04:08:57.695999
9 0 days 14:14:53.088000

In [150]: x5.task_a / np.timedelta64(1, 'h')  # convert to hours
Out[150]:
0    22.462968
1    24.345288
2    12.273576
3    35.170800
4    27.518208
5    29.348040
6    24.152664
7    13.897272
8    28.149360
9    14.248080
Name: task_a, dtype: float64

或到分钟

In [151]: x5.task_a / np.timedelta64(1, 'm')
Out[151]:
0    1347.77808
1    1460.71728
2     736.41456
3    2110.24800
4    1651.09248
5    1760.88240
6    1449.15984
7     833.83632
8    1688.96160
9     854.88480
Name: task_a, dtype: float64

使用total_seconds的另一种方式

In [153]: x5.task_a.dt.total_seconds() / 60
Out[153]:
0    1347.77808
1    1460.71728
2     736.41456
3    2110.24800
4    1651.09248
5    1760.88240
6    1449.15984
7     833.83632
8    1688.96160
9     854.88480
Name: task_a, dtype: float64

【讨论】:

  • 如果您不介意四舍五入到最接近的时间单位,您也可以使用x5.task_a.astype('timedelta64[m]') 或将m 替换为h 以表示分钟等(参见this answer)。在这种情况下,直方图 .hist() 而不是核密度估计 .plot.kde() 可能会更好。
  • 是的,这里也回答了转换类型stackoverflow.com/a/46223036/2137255
  • 请注意,如果您正在绘制数据,四舍五入可能不是一个好主意 - 它会改变绘图,让您对数据的形状产生错误的认识!
【解决方案2】:

您可以将 TimedeltaIndex 转换为 total_seconds

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

idx = pd.date_range('20140101', '20140201')
df = pd.DataFrame(index=idx)
df['col0'] = np.random.randn(len(idx))
diff_idx = (pd.Series(((idx-
idx.shift(1)).fillna(pd.Timedelta(0))).map(pd.TimedeltaIndex.total_seconds), 
index=idx)) # need to do this because we can't shift index
df['diff_dt'] = diff_idx
df['diff_dt'].plot()

【讨论】:

    猜你喜欢
    • 2016-06-17
    • 2014-12-09
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 2020-01-21
    相关资源
    最近更新 更多