我正在尝试从Pandas DataFrame连续日期获取大量数据.我的df看起来如下.
DateAnalyzed Val
1 2018-03-18 0.470253
2 2018-03-19 0.470253
3 2018-03-20 0.470253
4 2018-09-25 0.467729
5 2018-09-26 0.467729
6 2018-09-27 0.467729
在这个df中,我想得到前3行,做一些处理然后得到最后3行并对其进行处理.
我通过应用以下代码计算了1滞后的差异.
df['Delta']=(df['DateAnalyzed'] - df['DateAnalyzed'].shift(1))
但在那之后我无法弄清楚如何在没有迭代的情况下获得连续行的组.
解决方法:
看起来您需要两个布尔掩码:一个用于确定组之间的中断,另一个用于确定首先在组中的哪些日期.
还有一个棘手的部分可以通过例子充实.请注意,下面的df包含一个添加的行,该行在其之前或之后没有任何连续日期.
>>> df
DateAnalyzed Val
1 2018-03-18 0.470253
2 2018-03-19 0.470253
3 2018-03-20 0.470253
4 2017-01-20 0.485949 # < watch out for this
5 2018-09-25 0.467729
6 2018-09-26 0.467729
7 2018-09-27 0.467729
>>> df.dtypes
DateAnalyzed datetime64[ns]
Val float64
dtype: object
下面的答案假定您要完全忽略2017-01-20,而不进行处理. (如果您想要处理此日期,请参阅答案的结尾.)
第一:
>>> dt = df['DateAnalyzed']
>>> day = pd.Timedelta('1d')
>>> in_block = ((dt - dt.shift(-1)).abs() == day) | (dt.diff() == day)
>>> in_block
1 True
2 True
3 True
4 False
5 True
6 True
7 True
Name: DateAnalyzed, dtype: bool
现在,in_block将告诉您哪些日期在“连续”块中,但它不会告诉您每个日期属于哪些组.
下一步是自己派生分组:
>>> filt = df.loc[in_block]
>>> breaks = filt['DateAnalyzed'].diff() != day
>>> groups = breaks.cumsum()
>>> groups
1 1
2 1
3 1
5 2
6 2
7 2
Name: DateAnalyzed, dtype: int64
然后你可以用你选择的操作调用df.groupby(groups).
>>> for _, frame in filt.groupby(groups):
... print(frame, end='\n\n')
...
DateAnalyzed Val
1 2018-03-18 0.470253
2 2018-03-19 0.470253
3 2018-03-20 0.470253
DateAnalyzed Val
5 2018-09-25 0.467729
6 2018-09-26 0.467729
7 2018-09-27 0.467729
要将其合并到df中,请分配给它,隔离的日期将是NaN:
>>> df['groups'] = groups
>>> df
DateAnalyzed Val groups
1 2018-03-18 0.470253 1.0
2 2018-03-19 0.470253 1.0
3 2018-03-20 0.470253 1.0
4 2017-01-20 0.485949 NaN
5 2018-09-25 0.467729 2.0
6 2018-09-26 0.467729 2.0
7 2018-09-27 0.467729 2.0
如果你想要包括“孤独”日期,事情会变得更加简单:
dt = df['DateAnalyzed']
day = pd.Timedelta('1d')
in_block = ((dt - dt.shift(-1)).abs() == day) | (dt.diff() == day)
breaks = dt.diff() != day
groups = breaks.cumsum()
标签:python,pandas,datetime
来源: https://codeday.me/bug/20191008/1871863.html