簡體   English   中英

在 Pandas DataFrame 中查找連續日期組

[英]Find group of consecutive dates in Pandas DataFrame

我試圖從 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')
breaks = dt.diff() != day
groups = breaks.cumsum()

這里這里之后有類似的問題,有更具體的輸出要求。 由於這個更一般,我也想在這里做出貢獻。

我們可以使用一行代碼輕松地為連續的組分配一個唯一標識符:

df['grp_date'] = df.DateAnalyzed.diff().dt.days.ne(1).cumsum()

在這里,每次我們看到差異大於一天的日期時,我們都會為該日期添加一個值,否則它會保留之前的值,以便我們最終獲得每個組的唯一標識符。

查看輸出:

  DateAnalyzed       Val  grp_date
1   2018-03-18  0.470253         1
2   2018-03-19  0.470253         1
3   2018-03-20  0.470253         1
4   2018-09-25  0.467729         2
5   2018-09-26  0.467729         2
6   2018-09-27  0.467729         2

現在,很容易groupby “grp_date”,做任何你想用做applyagg


例子:

# Sum across consecutive days (or any other method from pandas groupby)
df.groupby('grp_date').sum()

# Get the first value and last value per consecutive days
df.groupby('grp_date').apply(lambda x: x.iloc[[0, -1]])
# or df.groupby('grp_date').head(n) for first n days

# Perform custom operation across target-columns
df.groupby('grp_date').apply(lambda x: (x['col1'] + x['col2']) / x['Val'].mean())

# Multiple operations for a target-column
df.groupby('grp_date').Val.agg(['min', 'max', 'mean', 'std'])

# and so on...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM