【问题标题】:Finding max date of the month in a list of pandas timeseries dates在熊猫时间序列日期列表中查找本月的最大日期
【发布时间】:2017-03-02 03:15:22
【问题描述】:

我有一个没有每个日期(即交易日期)的时间序列。系列可以在这里复制。

 dates=pd.Series(np.random.randint(100,size=30),index=pd.to_datetime(['2010-01-04', '2010-01-05', '2010-01-06', '2010-01-07',
           '2010-01-08', '2010-01-11', '2010-01-12', '2010-01-13',
           '2010-01-14', '2010-01-15', '2010-01-19', '2010-01-20',
           '2010-01-21', '2010-01-22', '2010-01-25', '2010-01-26',
           '2010-01-27', '2010-01-28', '2010-01-29', '2010-02-01',
           '2010-02-02', '2010-02-03', '2010-02-04', '2010-02-05',
           '2010-02-08', '2010-02-09', '2010-02-10', '2010-02-11',
           '2010-02-12', '2010-02-16']))

我想在我的日期列表中显示该月的最后一天,即:“2010-01-29”和“2010-02-16”

我看过Get the last date of each month in a list of dates in Python

更具体地说...

import pandas as pd
import numpy as np

df = pd.read_csv('/path/to/file/')          # Load a dataframe with your file
df.index = df['my_date_field']              # set the dataframe index with your date
dfg = df.groupby(pd.TimeGrouper(freq='M'))  # group by month / alternatively use MS for Month Start / referencing the previously created object

# Finally, find the max date in each month
dfg.agg({'my_date_field': np.max})

# To specifically coerce the results of the groupby to a list:
dfg.agg({'my_date_field': np.max})['my_date_field'].tolist()

...但不能完全弄清楚如何使其适应我的应用程序。提前致谢。

【问题讨论】:

  • dates.groupby(dates.index.month).apply(pd.Series.tail,1) 怎么样?
  • dfg = data.groupby(pd.TimeGrouper(freq='M')).max() 在您的数据上返回包含两行的数据框 - 2010-01-31、2010-02-28

标签: pandas python-datetime


【解决方案1】:

您可以尝试以下方法来获得所需的输出:

import numpy as np
import pandas as pd


dates=pd.Series(np.random.randint(100,size=30),index=pd.to_datetime(['2010-01-04', '2010-01-05', '2010-01-06', '2010-01-07',
           '2010-01-08', '2010-01-11', '2010-01-12', '2010-01-13',
           '2010-01-14', '2010-01-15', '2010-01-19', '2010-01-20',
           '2010-01-21', '2010-01-22', '2010-01-25', '2010-01-26',
           '2010-01-27', '2010-01-28', '2010-01-29', '2010-02-01',
           '2010-02-02', '2010-02-03', '2010-02-04', '2010-02-05',
           '2010-02-08', '2010-02-09', '2010-02-10', '2010-02-11',
           '2010-02-12', '2010-02-16']))

这个:

dates.groupby(dates.index.month).apply(pd.Series.tail,1).reset_index(level=0, drop=True)

或者这个:

dates[dates.groupby(dates.index.month).apply(lambda s: np.max(s.index))]

两者都应该产生如下内容:

#2010-01-29    43
#2010-02-16    48

将其转换为列表:

dates.groupby(dates.index.month).apply(pd.Series.tail,1).reset_index(level=0, drop=True).tolist()

或者:

dates[dates.groupby(dates.index.month).apply(lambda s: np.max(s.index))].tolist()

两者都产生类似:

#[43, 48]

如果您要处理超过一年的数据集,则需要同时按yearmonth 进行分组。以下应该会有所帮助:

import numpy as np
import pandas as pd


z = ['2010-01-04', '2010-01-05', '2010-01-06', '2010-01-07', 
'2010-01-08', '2010-01-11', '2010-01-12', '2010-01-13', 
'2010-01-14', '2010-01-15', '2010-01-19', '2010-01-20', 
'2010-01-21', '2010-01-22', '2010-01-25', '2010-01-26', 
'2010-01-27', '2010-01-28', '2010-01-29', '2010-02-01', 
'2010-02-02', '2010-02-03', '2010-02-04', '2010-02-05', 
'2010-02-08', '2010-02-09', '2010-02-10', '2010-02-11', 
'2010-02-12', '2010-02-16', '2011-01-04', '2011-01-05', 
'2011-01-06', '2011-01-07', '2011-01-08', '2011-01-11', 
'2011-01-12', '2011-01-13', '2011-01-14', '2011-01-15', 
'2011-01-19', '2011-01-20', '2011-01-21', '2011-01-22', 
'2011-01-25', '2011-01-26', '2011-01-27', '2011-01-28', 
'2011-01-29', '2011-02-01', '2011-02-02', '2011-02-03', 
'2011-02-04', '2011-02-05', '2011-02-08', '2011-02-09', 
'2011-02-10', '2011-02-11', '2011-02-12', '2011-02-16']

dates1 = pd.Series(np.random.randint(100,size=60),index=pd.to_datetime(z))

这个:

dates1.groupby((dates1.index.year, dates1.index.month)).apply(pd.Series.tail,1).reset_index(level=(0,1), drop=True)

或者:

dates1[dates1.groupby((dates1.index.year, dates1.index.month)).apply(lambda s: np.max(s.index))]

两者都产生类似:

# 2010-01-29    66
# 2010-02-16    80
# 2011-01-29    13
# 2011-02-16    10

我希望这证明有用。

【讨论】:

  • 这可以解决@Abdou 的问题。我实际上是自己尝试过的,但由于某种原因无法使其正常工作……看起来这是两个“groupby”级别的双引号。即:df.groupby((first, second))
  • 第一个示例可以用于数据框而不是系列。第二个示例可能不能与数据框一起使用。
  • @wlbsr groupby 级别没有引用。你指的是括号吗?如果是这样,那些需要在那里。此外,就像您在问题中指出的那样,该解决方案是为系列编写和测试的。如果您在数据帧上对此进行测试,您可能会得到不同的结果。请分享您在测试这些代码时遇到的错误。
【解决方案2】:

您可以通过monthapply 索引的最后一个值使用groupby

print (dates.groupby(dates.index.month).apply(lambda x: x.index[-1]))
1   2010-01-29
2   2010-02-16
dtype: datetime64[ns]

另一种解决方案:

print (dates.groupby(dates.index.month).apply(lambda x: x.index.max()))
1   2010-01-29
2   2010-02-16
dtype: datetime64[ns]

对于列表,首先将strftime转换为string

print (dates.groupby(dates.index.month)
            .apply(lambda x: x.index[-1]).dt.strftime('%Y-%m-%d').tolist())
['2010-01-29', '2010-02-16']

如果需要最后一个Month 值的值,请使用iloc

print (dates.groupby(dates.index.month).apply(lambda x: x.iloc[-1]))
1    55
2    48
dtype: int64

print (dates.groupby(dates.index.month).apply(lambda x: x.iloc[-1]).tolist())
[55, 48]

编辑:

对于yearmonth 需要将index to_period 转换为months

dates=pd.Series(np.random.randint(100,size=30),index=pd.to_datetime(
          ['2010-01-04', '2010-01-05', '2010-01-06', '2010-01-07',
           '2010-01-08', '2011-01-11', '2011-01-12', '2011-01-13',
           '2012-01-14', '2012-01-15', '2012-01-19', '2012-01-20',
           '2013-01-21', '2013-01-22', '2013-01-25', '2013-01-26',
           '2013-01-27', '2013-01-28', '2013-01-29', '2013-02-01',
           '2014-02-02', '2014-02-03', '2014-02-04', '2014-02-05',
           '2015-02-08', '2015-02-09', '2015-02-10', '2015-02-11',
           '2016-02-12', '2016-02-16']))
#print (dates)
print (dates.groupby(dates.index.to_period('m')).apply(lambda x: x.index[-1]))
2010-01   2010-01-08
2011-01   2011-01-13
2012-01   2012-01-20
2013-01   2013-01-29
2013-02   2013-02-01
2014-02   2014-02-05
2015-02   2015-02-11
2016-02   2016-02-16
Freq: M, dtype: datetime64[ns]

print (dates.groupby(dates.index.to_period('m'))
            .apply(lambda x: x.index[-1]).dt.strftime('%Y-%m-%d').tolist())
['2010-01-08', '2011-01-13', '2012-01-20', '2013-01-29', 
'2013-02-01', '2014-02-05', '2015-02-11', '2016-02-16']           
print (dates.groupby(dates.index.to_period('m')).apply(lambda x: x.iloc[-1]))
2010-01    68
2011-01    96
2012-01    53
2013-01     4
2013-02    16
2014-02    18
2015-02    41
2016-02    90
Freq: M, dtype: int64

print (dates.groupby(dates.index.to_period('m')).apply(lambda x: x.iloc[-1]).tolist())
[68, 96, 53, 4, 16, 18, 41, 90]

EDIT1:如果需要将period 转换为end of month 日期时间:

df = dates.groupby(dates.index.to_period('m')).apply(lambda x: x.index[-1])
df.index = df.index.to_timestamp('m')
print (df)
2010-01-31   2010-01-08
2011-01-31   2011-01-13
2012-01-31   2012-01-20
2013-01-31   2013-01-29
2013-02-28   2013-02-01
2014-02-28   2014-02-05
2015-02-28   2015-02-11
2016-02-29   2016-02-16
dtype: datetime64[ns]

【讨论】:

  • 根据我的问题和示例,以上所有答案都是正确的,但在实施时,我发现我需要澄清。如果数据延续多年,我正在寻找的是我每年每个月的日期列表(不是所有日期)中每月的最后一天。看起来按月分组给了我所有年份中所有月份的最后日期,而不是每年每个月的最后日期。在这里帮忙?我在考虑可能按年份分组,然后按日期分组,但我不确定语法。
  • 是的,除了日期/索引变为 2009-12 而不是保留实际日期 2009-12-31
  • 我不确定是否理解,您需要将期间转换为月末日期吗?查看上次编辑。
  • 其实这个答案比上面那个好一点,但是看看另一个答案,特别是下面的输出,上面写着:'Both yield something like:'
  • 好的,但是你问I would like the last day of the month in my list of dates ie: '2010-01-29' and '2010-02-16'。所以我认为这是你想要的输出。如果需要其他东西,最好是用样本创建新问题。所需的输出和您尝试的内容。因为没有它很难回答......
猜你喜欢
  • 2018-04-21
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-01
  • 2021-12-06
  • 2021-12-29
  • 2020-07-18
相关资源
最近更新 更多