简化了datetime列的pandas groupby聚合



我有这个pandas数据框架,它包含一个日期时间、一个整数和一个字符串列

from io import StringIO
import pandas as pd
data1 =  """Year        N   X
2008-01-01  2   A
2008-01-01  3   B
2008-01-01  6   C
2008-01-01  2   D
2010-01-01  7   A
2010-01-01  1   B
2010-01-01  8   C
2012-01-01  9   A
2012-01-01  4   B
2016-01-01  1   A"""
df = pd.read_csv(StringIO(data1), delim_whitespace=True, parse_dates=["Year"])

我可以将列N的count、min和max简单地聚合为:

df1 = df.groupby("X")["N"].agg(Count="count", Min="min", Max="max").reset_index()
print(df1)
X  Count  Min  Max
0  A      4    1    9
1  B      3    1    4
2  C      2    6    8
3  D      1    2    2

是否有一种方法可以实现相同的列Year只显示年份?我可以通过几个步骤来完成:

g = df.groupby("X")["Year"]
df2 = g.agg(Count= "count").reset_index()
df2["Start_date"] = g.min().dt.year.values
df2["End_date"] = g.max().dt.year.values
print(df2)
X  Count  Start_date  End_date
0  A      4        2008      2016
1  B      3        2008      2012
2  C      2        2008      2010
3  D      1        2008      2008

但是类似于上面的N版本,例如

df2 = df.groupby("X")["Year"].agg(Count="count", Min="min().dt.year.values", Max="max().dt.year.values").reset_index()

显然不起作用。是否有一种更简单的方法来聚合pandas groupby中的第一年和去年(除了像上面那样首先提取最小/最大日期的明显方法,然后将datetime列转换为年份列)?

  • 命名聚合
  • lambda日期序列函数
df = pd.read_csv(io.StringIO("""Year        N   X
2008-01-01  2   A
2008-01-01  3   B
2008-01-01  6   C
2008-01-01  2   D
2010-01-01  7   A
2010-01-01  1   B
2010-01-01  8   C
2012-01-01  9   A
2012-01-01  4   B
2016-01-01  1   A"""), sep="s+")
df.Year = pd.to_datetime(df.Year)
df = df.groupby("X").agg(N=("N","count"),
Start_date=("Year",lambda f: min(f.dt.year)),
End_date=("Year",lambda f: max(f.dt.year)))
End_date20082016200820122008201020082008

您是否尝试使用GroupBy.agg与命名聚合?

df.assign(Year=pd.to_datetime(df['Year']).dt.year).groupby('X').agg(
N=('N', 'count'), Start_date=('Year', 'first'), End_date=('Year', 'last'),)
N  Start_date  End_date
X                         
A  4        2008      2016
B  3        2008      2012
C  2        2008      2010
D  1        2008      2008

如果日期不是升序的,则分别使用'min''max',而不是'first''last'

这种方式允许您避免在grouper中使用lambda表达式(因此这是非常高性能的)。更多关于命名聚合的信息可以在我的文章中找到。

最新更新