如何发现pandas数据框索引之间的差距?

5

这段代码创建一个有10分钟时间范围索引的数据帧:

import pandas as pd 
import datetime as dt 

date_range = pd.date_range(end=dt.datetime(2017, 1, 6, 15, 00), periods=10, freq='10Min')

df = pd.DataFrame(index=date_range)
df['A'] = 1

print(df)

它的输出结果是:
                     A
2017-01-06 13:30:00  1
2017-01-06 13:40:00  1
2017-01-06 13:50:00  1
2017-01-06 14:00:00  1
2017-01-06 14:10:00  1
2017-01-06 14:20:00  1
2017-01-06 14:30:00  1
2017-01-06 14:40:00  1
2017-01-06 14:50:00  1
2017-01-06 15:00:00  1

我的问题是:

当索引之间存在间隙时,如何将以下三行中的列A设置为0?

例如,如果我们删除了一个特定行:

df = df[df.index != dt.datetime(2017, 1, 6, 14, 00)]

它的输出结果为:

                     A
2017-01-06 13:30:00  1
2017-01-06 13:40:00  1
2017-01-06 13:50:00  1
2017-01-06 14:10:00  1
2017-01-06 14:20:00  1
2017-01-06 14:30:00  1
2017-01-06 14:40:00  1
2017-01-06 14:50:00  1
2017-01-06 15:00:00  1

现在,在13:50之前缺少了10分钟的数据,因此以下的3个A行必须设置为0。

所以这将是期望的结果:

                     A
2017-01-06 13:30:00  1
2017-01-06 13:40:00  1
2017-01-06 13:50:00  1
2017-01-06 14:10:00  0
2017-01-06 14:20:00  0
2017-01-06 14:30:00  0
2017-01-06 14:40:00  1
2017-01-06 14:50:00  1
2017-01-06 15:00:00  1

有一个 Python 模拟器供你试用:https://repl.it/FaXZ/2

5个回答

5

您可以使用:

#get mask where difference
mask = df.index.to_series().diff() > pd.Timedelta('00:10:00')
#get position of index where True in mask
idx = mask.idxmax()
pos = df.index.get_loc(idx)
#add values by position
df.A.iloc[pos:pos + 2] = 0
print (df)
                     A
2017-01-06 13:30:00  1
2017-01-06 13:40:00  1
2017-01-06 13:50:00  1
2017-01-06 14:10:00  0
2017-01-06 14:20:00  0
2017-01-06 14:30:00  1
2017-01-06 14:40:00  1
2017-01-06 14:50:00  1
2017-01-06 15:00:00  1

df.A.iloc[pos:pos + 5] = 0
print (df)
                     A
2017-01-06 13:30:00  1
2017-01-06 13:40:00  1
2017-01-06 13:50:00  1
2017-01-06 14:10:00  0
2017-01-06 14:20:00  0
2017-01-06 14:30:00  0
2017-01-06 14:40:00  0
2017-01-06 14:50:00  0
2017-01-06 15:00:00  1

1
temp = df.index.to_series().diff() > pd.Timedelta('00:10:00')
df['A'] = 1- (temp | temp.shift(1)).astype(int)

将导致

                     A
2017-01-06 13:30:00  1
2017-01-06 13:40:00  1
2017-01-06 13:50:00  1
2017-01-06 14:10:00  0
2017-01-06 14:20:00  0
2017-01-06 14:30:00  1
2017-01-06 14:40:00  1
2017-01-06 14:50:00  1
2017-01-06 15:00:00  1

不错!但是如果我想将接下来的5个设置为0,而不是接下来的2个呢? - mllamazares
那不是问题中的内容;-) 例如,您可以在循环中链接对 temp | temp.shift(1) 的调用。 - languitar
酒吧有什么作用? - mnky9800n
这是用于 Pandas 数据框逐元素执行 OR 操作的操作符。https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#boolean-indexing - languitar

1
使用numpy:
import numpy as np

ii = np.where(np.diff(df.index.values) != np.timedelta64(10,'m'))[0]
for i in ii:
    df['A'].values[i+1:i+3] = 0

1
你可以将索引转换为列,然后使用.diff()创建一个名为diff的新列,该函数计算一列中两个连续条目之间的差异。结果列的第一个结果是NaN。之后,你可以简单地过滤出diff大于平均值的行。这样,如果你期望在连续索引之间的时间间隔发生变化,就不必更新代码。
import pandas as pd 
import datetime as dt 
date_range = pd.date_range(end=dt.datetime(2017, 1, 6, 15, 00), periods=10, freq='10Min')

df = pd.DataFrame(index=date_range)
df['A'] = 1
df.loc[:,'index'] = df.index.values.tolist()
df.loc[:, "diff"] = df['index'].diff()
print(df)
                     # A                index          diff
# 2017-01-06 13:30:00  1  1483709400000000000           NaN
# 2017-01-06 13:40:00  1  1483710000000000000  6.000000e+11
# 2017-01-06 13:50:00  1  1483710600000000000  6.000000e+11
# 2017-01-06 14:00:00  1  1483711200000000000  6.000000e+11
# 2017-01-06 14:10:00  1  1483711800000000000  6.000000e+11
# 2017-01-06 14:20:00  1  1483712400000000000  6.000000e+11
# 2017-01-06 14:30:00  1  1483713000000000000  6.000000e+11
# 2017-01-06 14:40:00  1  1483713600000000000  6.000000e+11
# 2017-01-06 14:50:00  1  1483714200000000000  6.000000e+11
# 2017-01-06 15:00:00  1  1483714800000000000  6.000000e+11

df_drop = df[df.index != dt.datetime(2017, 1, 6, 14, 00)]
df_drop.loc[:, "diff"] = df_drop['index'].diff()
print(df_drop)
                     # A                index          diff
# 2017-01-06 13:30:00  1  1483709400000000000           NaN
# 2017-01-06 13:40:00  1  1483710000000000000  6.000000e+11
# 2017-01-06 13:50:00  1  1483710600000000000  6.000000e+11
# 2017-01-06 14:10:00  1  1483711800000000000  1.200000e+12
# 2017-01-06 14:20:00  1  1483712400000000000  6.000000e+11
# 2017-01-06 14:30:00  1  1483713000000000000  6.000000e+11
# 2017-01-06 14:40:00  1  1483713600000000000  6.000000e+11
# 2017-01-06 14:50:00  1  1483714200000000000  6.000000e+11
# 2017-01-06 15:00:00  1  1483714800000000000  6.000000e+11

正如您所看到的,df_drop 数据框中的第四行 diff 值是其他值的两倍。


0
使用您的repl.it,我刚刚添加了一个pandas列作为计数器,并添加了一行缺失数据。
import numpy as np
import pandas as pd 
import datetime as dt 

date_range = pd.date_range(end=dt.datetime(2017, 1, 6, 15, 00), periods=10, freq='10Min')

df = pd.DataFrame(index=date_range)
df['A'] = 1
df['B'] = list(range(len(df['A'])))

print(df)

# now we delete an specific row
df = df[df.index != dt.datetime(2017, 1, 6, 14, 00)]

for i in range(0, df['B'].iloc[-1]):
  if str(i) not in str(df['B'].iloc[i]):
    df2 = df.T
    insert_row = [0,0]
    df2.insert(i, 'missing', insert_row)  
    df = df2.T

print(df)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接