从日期时间戳记获取开始和结束时间

时间:2019-10-26 15:38:50

标签: python pandas datetime data-science

我有一个带时间戳的CSV文件,以及有关表示开始(I)还是结束(F)的信息。 我想计算开始时间和结束时间之间的持续时间。

我正在尝试将其加载到熊猫,并按引用“ acao”(说明它是开始还是结束戳记)进行分组,将其拆开,然后使用fillna()能够从中获取表我可以计算出持续时间。

我正在使用的代码:

data = pd.read_csv(file_path, parse_dates=['time_stamp'])
y = data.sort_values(['referencia','time_stamp'])
        y = y.set_index(['referencia','acao'], append=True).time_stamp.unstack('acao')
        y = y[['I','F']]

预期结果如下(我希望我能够正确格式化表格):

+------------+----------------------------+----------------------------+
| referencia |             I              |             F              |
+------------+----------------------------+----------------------------+
|        111 | 2019-10-23 23:26:18.325750 |                            |
|        111 |                            | 2019-10-23 23:42:45.719985 |
|        123 | 2019-10-23 22:38:10.434322 |                            |
|        123 |                            | 2019-10-23 22:38:19.986666 |
|        123 | 2019-10-23 22:39:08.760218 |                            |
|        123 |                            | 2019-10-23 22:39:42.762875 |
|        123 | 2019-10-23 22:40:02.301749 |                            |
|        123 |                            | 2019-10-23 22:40:24.000795 |
|        123 | 2019-10-23 23:24:59.687386 |                            |
|        123 |                            | 2019-10-26 11:48:07.831072 |
|        133 | 2019-10-23 22:42:14.712779 |                            |
|        133 |                            | 2019-10-23 22:42:20.159414 |
|        156 | 2019-10-26 11:47:13.848750 |                            |
|        156 |                            | 2019-10-26 11:47:21.289268 |
|        199 | 2019-10-23 22:44:30.502311 |                            |
|        199 |                            | 2019-10-23 22:44:38.154283 |
|        555 | 2019-10-23 23:34:35.322073 |                            |
|        555 |                            | 2019-10-26 11:48:13.330636 |
+------------+----------------------------+----------------------------+

但是不幸的是,我只能得到:

+------------+----------------------------+----------------------------+
| referencia |             I              |             F              |
+------------+----------------------------+----------------------------+
|        123 | 2019-10-23 22:38:10.434322 |                            |
|        123 |                            | 2019-10-23 22:38:19.986666 |
|        123 | 2019-10-23 22:39:08.760218 |                            |
|        123 |                            | 2019-10-23 22:39:42.762875 |
|        123 | 2019-10-23 22:40:02.301749 |                            |
|        123 |                            | 2019-10-23 22:40:24.000795 |
|        133 | 2019-10-23 22:42:14.712779 |                            |
|        133 |                            | 2019-10-23 22:42:20.159414 |
|        199 | 2019-10-23 22:44:30.502311 |                            |
|        199 |                            | 2019-10-23 22:44:38.154283 |
|        123 | 2019-10-23 23:24:59.687386 |                            |
|        111 | 2019-10-23 23:26:18.325750 |                            |
|        555 | 2019-10-23 23:34:35.322073 |                            |
|        111 |                            | 2019-10-23 23:42:45.719985 |
|        156 | 2019-10-26 11:47:13.848750 |                            |
|        156 |                            | 2019-10-26 11:47:21.289268 |
|        123 |                            | 2019-10-26 11:48:07.831072 |
|        555 |                            | 2019-10-26 11:48:13.330636 |
+------------+----------------------------+----------------------------+

我无法进行分组,因为尝试时会出现以下错误: “ ValueError:索引包含重复的条目,无法重塑”

我忘了附加源数据,它不在下面:

utilizador,referencia,time_stamp,acao
AG,123,2019-10-23 22:38:10.434322,I
AG,123,2019-10-23 22:38:19.986666,F
AG,123,2019-10-23 22:39:08.760218,I
AG,123,2019-10-23 22:39:42.762875,F
AG,123,2019-10-23 22:40:02.301749,I
AG,123,2019-10-23 22:40:24.000795,F
AG,133,2019-10-23 22:42:14.712779,I
AG,133,2019-10-23 22:42:20.159414,F
AG,199,2019-10-23 22:44:30.502311,I
AG,199,2019-10-23 22:44:38.154283,F
AG,123,2019-10-23 23:24:59.687386,I
AG,111,2019-10-23 23:26:18.325750,I
AG,555,2019-10-23 23:34:35.322073,I
AG,111,2019-10-23 23:42:45.719985,F
AA,156,2019-10-26 11:47:13.848750,I
AG,156,2019-10-26 11:47:21.289268,F
AG,123,2019-10-26 11:48:07.831072,F
AG,555,2019-10-26 11:48:13.330636,F

1 个答案:

答案 0 :(得分:1)

我认为:

  • I F 列均为 datetime 类型,
  • referencia 是一个“普通”列(不是索引)。

为了使打印输出保持合理的水平尺寸, 我从您的数据中删除了几分之一秒,所以我的结果 与您的有所不同。

从向上移动 F 列1单元格中的数据开始:

df.F = df.F.shift(-1)

然后使用 NaT 删除行:

df.dropna(inplace=True)

结果是:

    referencia                   I                   F
0          111 2019-10-23 23:26:18 2019-10-23 23:42:45
2          123 2019-10-23 22:38:10 2019-10-23 22:38:19
4          123 2019-10-23 22:39:08 2019-10-23 22:39:42
6          123 2019-10-23 22:40:02 2019-10-23 22:40:24
8          123 2019-10-23 23:24:59 2019-10-26 11:48:07
10         133 2019-10-23 22:42:14 2019-10-23 22:42:20
12         156 2019-10-26 11:47:13 2019-10-26 11:47:21
14         199 2019-10-23 22:44:30 2019-10-23 22:44:38
16         555 2019-10-23 23:34:35 2019-10-26 11:48:13

然后将两个时间值都放在同一行中,以计算 duration 列,请运行:

df['duration'] = df.F - df.I

对于我的源数据,结果是:

    referencia                   I                   F        duration
0          111 2019-10-23 23:26:18 2019-10-23 23:42:45 0 days 00:16:27
2          123 2019-10-23 22:38:10 2019-10-23 22:38:19 0 days 00:00:09
4          123 2019-10-23 22:39:08 2019-10-23 22:39:42 0 days 00:00:34
6          123 2019-10-23 22:40:02 2019-10-23 22:40:24 0 days 00:00:22
8          123 2019-10-23 23:24:59 2019-10-26 11:48:07 2 days 12:23:08
10         133 2019-10-23 22:42:14 2019-10-23 22:42:20 0 days 00:00:06
12         156 2019-10-26 11:47:13 2019-10-26 11:47:21 0 days 00:00:08
14         199 2019-10-23 22:44:30 2019-10-23 22:44:38 0 days 00:00:08
16         555 2019-10-23 23:34:35 2019-10-26 11:48:13 2 days 12:13:38

在发布源数据之后进行编辑

要将 time_stamp 列作为“真实”时间戳(不是字符串),请将 parse_dates = [2] 参数传递给 read_csv 。 / p>

然后,要重新格式化您的DataFrame,请采用以下方法:

定义重新格式化函数,该函数将应用于每个组(连续的两对行):

def reformat(grp):
    tStart = grp.iloc[0, 2]
    tEnd = grp.iloc[1, 2]
    return pd.Series(grp.iloc[0, 0:3].tolist() + [tEnd, tEnd - tStart],
        index=['utilizador', 'referencia', 'start', 'end', 'duration'])

然后将其应用:

df = df.groupby(np.arange(len(df.index)) // 2).apply(reformat)

对于源数据,秒的小数部分都丢失了,结果是:

  utilizador  referencia               start                 end duration
0         AG         123 2019-10-23 22:38:10 2019-10-23 22:38:19 00:00:09
1         AG         123 2019-10-23 22:39:08 2019-10-23 22:39:42 00:00:34
2         AG         123 2019-10-23 22:40:02 2019-10-23 22:40:24 00:00:22
3         AG         133 2019-10-23 22:42:14 2019-10-23 22:42:20 00:00:06
4         AG         199 2019-10-23 22:44:30 2019-10-23 22:44:38 00:00:08
5         AG         123 2019-10-23 23:24:59 2019-10-23 23:26:18 00:01:19
6         AG         555 2019-10-23 23:34:35 2019-10-23 23:42:45 00:08:10
7         AA         156 2019-10-26 11:47:13 2019-10-26 11:47:21 00:00:08
8         AG         123 2019-10-26 11:48:07 2019-10-26 11:48:13 00:00:06

再说一遍:我注意到您的数据有些混乱,例如你有 仅一行

  • utilizador =='AA'
  • utilizador =='AG' referencia == 156

使用我的方案:

  • 输入文件应包含有关的连续行对 相同的 utilizador referencia
  • 每对应该在 acao =='I'的第一行显示第二行 表示 acao =='F'

或者至少应该可以按此顺序对数据进行排序。

或者也许指示的2行应该用于相同的 utilizador (它们“彼此配对”)?

编辑2

我将数据中的 AG,156 更改为 AA,156 (将上一行与该行成对)。

然后我将排序添加到您的数据中,然后应用重新格式化

df = df.sort_values(['utilizador', 'referencia', 'time_stamp'])\
    .groupby(np.arange(len(df.index)) // 2).apply(reformat)

对于此类更改的数据,结果为:

  utilizador  referencia               start                 end        duration
0         AA         156 2019-10-26 11:47:13 2019-10-26 11:47:21 0 days 00:00:08
1         AG         111 2019-10-23 23:26:18 2019-10-23 23:42:45 0 days 00:16:27
2         AG         123 2019-10-23 22:38:10 2019-10-23 22:38:19 0 days 00:00:09
3         AG         123 2019-10-23 22:39:08 2019-10-23 22:39:42 0 days 00:00:34
4         AG         123 2019-10-23 22:40:02 2019-10-23 22:40:24 0 days 00:00:22
5         AG         123 2019-10-23 23:24:59 2019-10-26 11:48:07 2 days 12:23:08
6         AG         133 2019-10-23 22:42:14 2019-10-23 22:42:20 0 days 00:00:06
7         AG         199 2019-10-23 22:44:30 2019-10-23 22:44:38 0 days 00:00:08
8         AG         555 2019-10-23 23:34:35 2019-10-26 11:48:13 2 days 12:13:38

您可能想要什么。