使用pandas在同一索引的列中查找连续天数的开始和结束日期

Gun*_*Gun 4 python dataframe pandas

我有一个数据框df

df =

index  date        hats
A1     01-01-2020  5
A1     02-01-2020  10
A1     03-01-2020  16
A1     04-01-2020  16
A1     21-01-2020  9
A1     22-01-2020  8
A1     23-01-2020  7
A6     20-03-2020  5
A6     21-03-2020  5
A8     30-07-2020  12
Run Code Online (Sandbox Code Playgroud)

这里,前四行是连续的天数。我想知道数据框中所有这些连续天数的开始日期和结束日期。如果像 wiseA8索引那样的系列中只有一天,df那么开始日期和结束日期将相同。此外,我也有兴趣了解df['hats']连续天数系列中列中的最高值,并将其日期与其 datehigh_hat一起返回到单独的列中high_hat_date。如果在一系列连续天数中有两个或更多相等的高值,则在新列中num_hat写入高值出现的次数,并在 中写入第一个出现日期high_hat_date

上述数据框的示例输出如下:

index   start_date    end_date    high_hat    high_hat_date   num_hat
A1      01-01-2020    04-01-2020  16          03-01-2020      2
A1      21-01-2020    23-01-2020  9           21-01-2020      1
A6      20-03-2020    21-03-2020  5           20-03-2020      2
A8      30-07-2020    30-07-2020  12          30-07-2020      1     
Run Code Online (Sandbox Code Playgroud)

高度赞赏这方面的任何帮助。

Shu*_*rma 5

首先使用pd.to_datetimedate列转换为熊猫datetime系列:

df['date'] = pd.to_datetime(df['date'], dayfirst=True)
Run Code Online (Sandbox Code Playgroud)

然后使用:

g = df.groupby('index')['date'].diff().dt.days.ne(1).cumsum() # STEP A
m = df.groupby(['index', g])['hats'].transform('max').eq(df['hats']) # STEP B

df = df.assign(high_hats=df['hats'].mask(~m), high_date=df['date'].mask(~m)) # STEP C

dct = {'start_date': ('date', 'first'), 'end_date': ('date', 'last'), 'high_hat': ('hats', 'max'),
       'high_hat_date': ('high_date', 'first'), 'num_hats': ('high_hats', 'count')}
df1 = df.groupby(['index', g]).agg(**dct).reset_index().drop('date', 1) # STEP D
Run Code Online (Sandbox Code Playgroud)

细节:

步骤 A:使用DataFrame.groupbyonindex和 use groupby.diffondate计算连续日期之间经过的天数,然后使用Series.dt.days+Series.neSeries.cumsum创建一个分组系列g,这将需要在连续日期上对数据框进行分组。

# print(g)
0    1
1    1
2    1
3    1
4    2
5    2
6    2
7    3
8    3
9    4
Name: date, dtype: int64
Run Code Online (Sandbox Code Playgroud)

步骤 B:使用DataFrame.groupbyonindexgusegroupby.transform来转换列hatsmax然后使用Series.eq将其与hats列相等以创建布尔掩码m

# print(m)
0    False
1    False
2     True
3     True
4     True
5    False
6    False
7     True
8     True
9     True
Name: hats, dtype: bool
Run Code Online (Sandbox Code Playgroud)

步骤 C:接下来用于DataFrame.assign分配两个新列high_hatshigh_date它们将STEP D用于计算high_hat_datenum_hats

# print(df)    
  index       date  hats  high_hats  high_date
0    A1 2020-01-01     5        NaN        NaT
1    A1 2020-01-02    10        NaN        NaT
2    A1 2020-01-03    16       16.0 2020-01-03
3    A1 2020-01-04    16       16.0 2020-01-04
4    A1 2020-01-21     9        9.0 2020-01-21
5    A1 2020-01-22     8        NaN        NaT
6    A1 2020-01-23     7        NaN        NaT
7    A6 2020-03-20     5        5.0 2020-03-20
8    A6 2020-03-21     5        5.0 2020-03-21
9    A8 2020-07-30    12       12.0 2020-07-30
Run Code Online (Sandbox Code Playgroud)

步骤 D:使用DataFrame.groupbyonindexg并使用聚合字典聚合数据框,dct其中包含agg要应用的所有列及其相应的函数。

# print(df1)
  index start_date   end_date  high_hat high_hat_date  num_hats
0    A1 2020-01-01 2020-01-04        16    2020-01-03         2
1    A1 2020-01-21 2020-01-23         9    2020-01-21         1
2    A6 2020-03-20 2020-03-21         5    2020-03-20         2
3    A8 2020-07-30 2020-07-30        12    2020-07-30         1
Run Code Online (Sandbox Code Playgroud)

  • @ShubhamSharma 很棒的代码和指南,特别是竭尽全力超链接到文档。这将是一个很好的问题和答案供人们研究。我需要自己研究一下:) (2认同)