计算数据帧中多行的日期时间差异

时间:2017-05-10 08:47:21

标签: python pandas dataframe

我在数据框中有关于日期时间的python相关问题。我通过df

导入了以下pd.read_csv()
    datetime             label  d_time
0   2017-01-03 23:52:00            
1   2017-01-03 23:53:00  A   
2   2017-01-03 23:54:00  A   
3   2017-01-03 23:55:00  A   
4   2017-01-04 00:01:00     
5   2017-01-04 00:02:00  B
6   2017-01-04 00:06:00  B
7   2017-01-04 00:09:00  B
8   2017-01-04 00:11:00  B
9   2017-01-04 00:12:00  
10  2017-01-04 00:14:00  
11  2017-01-04 00:16:00  
12  2017-01-04 00:18:00  C
13  2017-01-04 00:20:00  C
14  2017-01-04 00:22:00  

我想知道用A,B,C标记的行的时差,如下所示:

    datetime             label  d_time
0   2017-01-03 23:52:00            
1   2017-01-03 23:53:00  A      0:02
2   2017-01-03 23:54:00  A   
3   2017-01-03 23:55:00  A   
4   2017-01-04 00:01:00     
5   2017-01-04 00:02:00  B      0:09 
6   2017-01-04 00:06:00  B
7   2017-01-04 00:09:00  B
8   2017-01-04 00:11:00  B
9   2017-01-04 00:12:00  
10  2017-01-04 00:14:00  
11  2017-01-04 00:16:00  
12  2017-01-04 00:18:00  C      0:02 
13  2017-01-04 00:20:00  C 
14  2017-01-04 00:22:00  

因此d_time应该是标记行的总时差。有约。 100种不同的标签,它们可以从1到x连续变化。这个计算必须在100万行中完成,因此循环可能不起作用。有人知道怎么做这个吗?提前致谢。

2 个答案:

答案 0 :(得分:0)

如果日期时间是datetime个对象(或pandas.TimeStamp),您可以使用此for循环

a_rows = []
for row in df.itertuples():
    if row.label == 'A':
        a_rows.append(row)
    elif a_rows:
        d_time = a_rows[-1].datetime - a_rows[0].datetime
        df.loc[a_rows[0].Index, 'd_time'] = d_time
        a_rows = []

有了这个结果

    datetime    label   d_time
0   2017-01-03 23:52:00     
1   2017-01-03 23:53:00 A   0 days 00:02:00
2   2017-01-03 23:54:00 A   
3   2017-01-03 23:55:00 A   
4   2017-01-04 00:01:00     
5   2017-01-04 00:02:00 A   0 days 00:07:00
6   2017-01-04 00:06:00 A   
7   2017-01-04 00:09:00 A   
8   2017-01-04 00:11:00     

如果需要,您可以稍后格式化timedelta对象。

如果日期时间列为string,您可以使用df['datetime'] = pd.to_datetime(df['datetime'])轻松转换em

答案 1 :(得分:0)

假设连续标签全部相同,并以1 nan

分隔

你可以做这样的事情

idx = pd.Series(df[pd.isnull(df['label'])].index)

idx_begin = idx.iloc[:-1] + 1
idx_end = idx.iloc[1:] - 1

d_time = df.loc[idx_end, 'datetime'].reset_index(drop=True) - df.loc[idx_begin, 'datetime'].reset_index(drop=True)
d_time.index = idx_begin
df.loc[idx_begin, 'd_time'] = d_time

如果您的数据集看起来不同,您可能会采用不同的方式来访问idx_beginidx_end,但这适用于您发布的数据集

多个连续nan s

如果有多个连续的nan - 值,您可以通过将其添加到结尾来解决此问题

df.loc[df[pd.isnull(df['label'])].index, 'd_time'] = None

连续不同的标签

idx = df[(df['label'] != df['label'].shift(1)) & (pd.notnull(df['label']) | (pd.notnull(df['label'].shift(1))))].index
idx_begin = idx[:-1]
idx_end = idx[1:] -1

这将不同的标签标记为不同的开始和开始。要使其工作,您需要将df.loc[df[pd.isnull(df['label'])].index, 'd_time'] = None添加到最后

& (pd.notnull(df['label']) | (pd.notnull(df['label'].shift(1)))部分是因为None != None

结果

    datetime    label   d_time
0   2017-01-03 23:52:00     NaN     NaN
1   2017-01-03 23:53:00     A   NaN
2   2017-01-03 23:54:00     A   NaN
3   2017-01-03 23:52:00     NaN     NaN
4   2017-01-03 23:53:00     B   NaN
5   2017-01-03 23:54:00     B   NaN
6   2017-01-03 23:55:00     NaN     NaN
7   2017-01-03 23:56:00     NaN     NaN
8   2017-01-03 23:57:00     NaN     NaN
9   2017-01-04 00:02:00     A   NaN
10  2017-01-04 00:06:00     A   NaN
11  2017-01-04 00:09:00     A   NaN
12  2017-01-04 00:02:00     B   NaN
13  2017-01-04 00:06:00     B   NaN
14  2017-01-04 00:09:00     B   NaN
15  2017-01-04 00:11:00     NaN     NaN

产量

    datetime    label   d_time
0   2017-01-03 23:52:00     NaN     NaT
1   2017-01-03 23:53:00     A   00:01:00
2   2017-01-03 23:54:00     A   NaT
3   2017-01-03 23:52:00     NaN     NaT
4   2017-01-03 23:53:00     B   00:01:00
5   2017-01-03 23:54:00     B   NaT
6   2017-01-03 23:55:00     NaN     NaT
7   2017-01-03 23:56:00     NaN     NaT
8   2017-01-03 23:57:00     NaN     NaT
9   2017-01-04 00:02:00     A   00:07:00
10  2017-01-04 00:06:00     A   NaT
11  2017-01-04 00:09:00     A   NaT
12  2017-01-04 00:02:00     B   00:07:00
13  2017-01-04 00:06:00     B   NaT
14  2017-01-04 00:09:00     B   NaT
15  2017-01-04 00:11:00     NaN     NaT

最后一个系列

如果最后一行与之前的标签相比没有更改的标签,则最后一个系列将不会注册。

您可以通过在第一行

之后添加此内容来阻止此操作
if idx[-1] != df.index[-1]:
    idx = idx.append(df.index[[-1]]+1)