【问题标题】:How to get last day of each month from a data frame and remove the rest from the dataframe?如何从数据框中获取每个月的最后一天并从数据框中删除其余日期?
【发布时间】:2021-07-03 18:34:25
【问题描述】:

大家好, 图片是我正在学习python的数据框。

从这个数据框中,我试图找到每年 12 月最后一天的行记录。我的目标是在数据框中以黄色突出显示记录并删除白色行。

例如,对于 2010 年,我只想保留第 3 条记录并删除第 1 到第 2 行。 至于 2011 年,我想删除第 4 到 7 行并保留第 8 行。

下面是我写的代码。我打算使用循环查找我要保留的记录并删除其余记录。

为了使用月份值保留记录,我设法通过保留 12 月并删除 1 月到 11 月的记录来实现我的目标

然而,几天来(最后 3 行代码),我意识到最后一天在数据框中并不总是以 31 结束,我无法使用我的初始逻辑来删除。

如果有更好的解决方案可以在数据框中找到月份的最后一天并删除其余日期,我可以寻求帮助吗?

谢谢

amalgamate=pd.read_excel("amalgamate.xlsx")

##Create last 3 columns to segregate Year, Month and Day.
amalgamate["Date"] = pd.to_datetime(amalgamate["Date"], errors = "raise", format = "%Y-%m-%d")
amalgamate["Year"]=amalgamate["Date"].dt.year
amalgamate["Month"]=amalgamate["Date"].dt.month
amalgamate["Day"]=amalgamate["Date"].dt.day


listofMonth=amalgamate.Month.unique()
listofDay=amalgamate.Day.unique()

#Loop through the records and remove records that are not Dec for each year
for eachmonth in listofMonth:
    if eachmonth !=12:
        amalgamate=amalgamate[amalgamate.Month != eachmonth]
        
#Loop through the records and remove records that are not 31 for each month
for eachday in listofDay:
    if eachday !=31:
        amalgamate=amalgamate[amalgamate.Day != eachday]

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    这是一个单行程序,它将通过按 Date 分组并将 pd.Grouper 设置为一个月来过滤月份的最后几天,然后从每个组中获取最后一行:

    df.loc[df.groupby(pd.Grouper(key='Date', freq='1M')).Date.idxmax()]
    

    【讨论】:

    • 不知道为什么,但我收到此错误 ValueError:尝试获取空序列的 argmax。我尝试使用 .sum() 和 .mean(),组对象中有值。
    【解决方案2】:

    正如您在问题开始时提到的,您希望找到每年 12 月的最后一天,您可以按年份对日期进行分组,并按 @ 获取组中的最后一个条目987654321@,如下:

    df.groupby(df['Date'].dt.year, as_index=False).last()
    

    如果您还想找到一个月的最后一天(正如您在问题末尾提到的),您可以按年和月对日期进行分组,并通过GroupBy.last() 获取组中的最后一个条目,如如下:

    df.groupby([df['Date'].dt.year, df['Date'].dt.month], as_index=False).last()
    

    【讨论】:

    • 谢谢。为我工作。干杯
    【解决方案3】:

    您可以使用 pandas groupby 查找每年的最后(即最大)月份和最后一天,然后合并数据框以仅过滤具有最后一个月和日期的行。正如您不需要假设数据中 12 月的最后一天是 31 日一样,您也不必假设数据中一年中的最后一个月是 12 月。有多种方法可以做到这一点,并且您可以按不同的顺序执行以下步骤。这是我认为最容易理解的一个:

    row1list = [2010, 12, 28]
    row2list = [2010, 12, 20]
    
    row3list = [2011, 11, 20]
    row4list = [2011, 11, 15]
    row5list = [2011, 10, 30]
    df = pd.DataFrame([row1list, row2list, row3list, row4list, row5list], columns=['year', 'month', 'day'])
    
    # find last day for every combo of year, month
    df_last_day_per_year_month = df.groupby(['year', 'month'], as_index=False).agg({
        'day': max})
    
    # find last month for every year, using only the rows with max day per year, month 
    df_last_month_per_year = df_last_day_per_year_month.groupby('year', as_index=False).agg({
        'month': max})
    
    # keep only the last month by comparing month values to last month per year
    df_last_month_per_year = df_last_month_per_year.rename(columns={'month':'last_month'})
    
    df_last_day_per_year_month = df_last_day_per_year_month.merge(df_last_month_per_year, on='year', how='left')
    
    df_last_day_per_year_month = df_last_day_per_year_month[df_last_day_per_year_month['month'] == df_last_day_per_year_month['last_month']]
    
    # don't need 'last_month' column anymore so delete it
    del df_last_day_per_year_month['last_month']
    
    # inner merge to filter original df to keep only the dates that are max month, day per year
    df = df.merge(df_last_day_per_year_month, on=['year', 'month', 'day'], how='inner')
    
    print(df)
    #    year  month  day
    # 0  2010     12   28
    # 1  2011     11   20
    
    
    

    【讨论】:

      猜你喜欢
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多