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

How can I count the number of days between a 1 and the next 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)

我认为像下面这样的东西应该有用,首先有一个带有日期索引的系列:

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,所以我忽略这些。

您可以像 itertool.groupby 一样在此处使用 groupby 进行尝试。提取每组的第一个索引。由于您必须找到差异 b/w 两组,因此 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]

从创建一个包含 date 列的 DataFrame 开始 dates 转换为 datetime 和由 values 组成的 val 列:

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

得到结果的思路是:

  • 获取 val == 0 的日期(对于其他行采用 NaT)。
  • 执行“向后填充”。
  • 减去日期.
  • 从上面的结果 (timedelta) 得到天数。
  • 0 填充未完成的 NaT 值(如果有)(在您的情况下 这与最后两行有关,后面没有任何“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.

的行