如何计算从1到下一个0之间的天数



[我附上了我的系列的图片和获得该系列的代码,我如何获得1到下一个0之间的天数。例如,第一个1和下一个0之间的天数为4天(8月1日至8月5日(,下一个1和0之间的日期也为4天[8月8日至8日12日1

values = [1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]

dates =['2019-08-01', '2019-08-02', '2019-08-05', '2019-08-06',
'2019-08-07', '2019-08-08', '2019-08-09', '2019-08-12',
'2019-08-13', '2019-08-14', '2019-08-15', '2019-08-16',
'2019-08-19', '2019-08-20', '2019-08-21', '2019-08-22',
'2019-08-23', '2019-08-26', '2019-08-27', '2019-08-28',
'2019-08-29', '2019-08-30']
pd.Series(values, index = dates)

您可以在此处使用类似itertool.groupby的groupby来尝试此操作。每组提取第一个指标。由于你必须找到两组的差异,所以必须有相同数量的1组和0组,如果不是这样,那么删除最后一组。

s = pd.Series(values, index = pd.to_datetime(dates))
g = s.ne(s.shift()).cumsum()
vals = s.groupby(g).apply(lambda x:x.index[0])
# vals
1    2019-08-01
2    2019-08-05
3    2019-08-08
4    2019-08-12
5    2019-08-13
6    2019-08-14
7    2019-08-16
8    2019-08-23
9    2019-08-29
dtype: object

现在我们没有相同数量的1组和0组,所以放弃组索引。并制作大小为2的块,即现在,每个块都有1和0组索引。

end = None if not len(vals)%2 else -1
vals = vals.iloc[:end].values.reshape((-1, 2))
# vals 
array([['2019-08-01T00:00:00.000000000', '2019-08-05T00:00:00.000000000'],
['2019-08-08T00:00:00.000000000', '2019-08-12T00:00:00.000000000'],
['2019-08-13T00:00:00.000000000', '2019-08-14T00:00:00.000000000'],
['2019-08-16T00:00:00.000000000', '2019-08-23T00:00:00.000000000']],
dtype='datetime64[ns]')

现在,我们必须使用np.diff来找到差异。

days = np.diff(vals, axis=1).squeeze()
out = pd.Series(days)
# out
0   4 days
1   4 days
2   1 days
3   7 days
dtype: timedelta64[ns]

我认为下面这样的方法应该有效,首先要有一个带有日期索引的系列:

ds = pd.Series(values, index = pd.to_datetime(dates))

然后计算连续值之间的差值:

delta = ds - ds.shift(fill_value=ds[0]-1)

它看起来像这样:

pd.DataFrame({'value':ds,'delta':delta})

value   delta
2019-08-01  1   1
2019-08-02  1   0
2019-08-05  0   -1
2019-08-06  0   0
2019-08-07  0   0
2019-08-08  1   1
2019-08-09  1   0
2019-08-12  0   -1
2019-08-13  1   1
2019-08-14  0   -1

所以你需要的开始日期是delta为1的时候,下一个零是-1的时候。因此:

starts = ds.index[delta == 1]
ends = ds.index[delta == -1]
(ends - starts[:len(ends)]).days
Int64Index([4, 4, 1, 7], dtype='int64')

注意,有些情况下,在数据帧的末尾,有1,但它们不会翻转为0,所以我忽略了这些。

从创建数据帧开始,数据帧的日期列由日期转换为日期时间和由值组成的val

df = pd.DataFrame({'date': pd.to_datetime(dates), 'val': values})

得到结果的想法是:

  • 获取日期,其中val==0(对于其他行,取NaT(
  • 执行";向后填充">
  • 减去日期
  • 根据以上结果(timedelta(获得天数
  • 0填充未完成的NaT值(如果有((在您的情况下这涉及最后2行,后面没有任何"0">0行"(
  • 将结果保存在dist列中

这样做的代码是:

df['dist'] = (df.date.where(df.val == 0).bfill(0) - df.date)
.dt.days.fillna(0, downcast='infer')

结果是:

date  val  dist
0  2019-08-01    1     4
1  2019-08-02    1     3
2  2019-08-05    0     0
3  2019-08-06    0     0
4  2019-08-07    0     0
5  2019-08-08    1     4
6  2019-08-09    1     3
7  2019-08-12    0     0
8  2019-08-13    1     1
9  2019-08-14    0     0
10 2019-08-15    0     0
11 2019-08-16    1     7
12 2019-08-19    1     4
13 2019-08-20    1     3
14 2019-08-21    1     2
15 2019-08-22    1     1
16 2019-08-23    0     0
17 2019-08-26    0     0
18 2019-08-27    0     0
19 2019-08-28    0     0
20 2019-08-29    1     0
21 2019-08-30    1     0

(dist列是以天为单位的距离(。

如果需要,请仅从上面的结果中获取带有val!=的行0

相关内容

最新更新