繁体   English   中英

如何操作 pandas 日期时间对象以获取上个月的最后日期

[英]How to manipulate pandas datetime objects to get the last date of previous month

我有一个 pandas dataframe 并想将所有日期变成上个月的最后一个日期。 例如“2020-02-04”应该变成“2020-01-31”,“2020-03-03”应该变成“2020-02-28”等等。 我的 df 看起来像这样(在月份列中,我已经有了适合我想要的日期的月份):

In[76]: dfall[["date", "month"]]
Out[76]: 
       date    month
0 2020-02-04      1
1 2020-03-03      2
2 2020-04-02      3
3 2020-05-05      4
4 2020-06-03      5
5 2020-07-02      6

现在我尝试了这个:

import calendar
import datetime
today = datetime.now()
dfall.date = str(today.year) + "-" + str(dfall.month) + "-" + str(calendar.monthrange(today.year,dfall.month)[1])

这个想法是通过将字符串添加在一起来构建新日期。 但是这段代码引发了一个错误:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

我知道错误来自这部分: str(calendar.monthrange(today.year,dfall.month)[1]) (没有这部分代码运行没有错误,但结果不是我想要的)。 这可能是因为 python 不知道从dfall.month取哪个月份。 有人知道我该如何处理这个问题吗?

作为替代方案,您可以尝试以下方法:

dfall.date=dfall.date.apply(lambda x: x.replace(day=1)- pd.Timedelta(days=1))

如果dfall.date是字符串类型,请尝试以下操作:

dfall.date=pd.to_datetime(dfall.date).apply(lambda x: x.replace(day=1)- pd.Timedelta(days=1))

您可以尝试由Kyle Barron制作的另一种矢量化替代方案,以避免使用df.apply(lambda x: x.replace(day=1))并将性能提高到8.5 倍:

def vec_dt_replace(series, year=None, month=None, day=None):
    return pd.to_datetime(
        {'year': series.dt.year if year is None else year,
         'month': series.dt.month if month is None else month,
         'day': series.dt.day if day is None else day})
#dfall.date=pd.to_datetime(dfall.date) #(if dfall.date is type string)
dfall.date=vec_dt_replace(dfall.date,day=1)- pd.Timedelta(days=1)

如果您想保留原始解决方案,则:

  • str(dfall.month)更改为dfall.month.astype(str)
  • str(calendar.monthrange(today.year,dfall.month)[1])更改为dfall.month.apply(lambda x:calendar.monthrange(today.year,x)[1]).astype(str)
  • 获得字符串后,您应该将其转换为日期时间: pd.to_datetime(dfall.date)
import calendar
import datetime
today = datetime.datetime.now()
dfall.date = str(today.year) + "-" + dfall.month.astype(str) + "-" + dfall.month.apply(lambda x:calendar.monthrange(today.year,x)[1]).astype(str)
dfall.date = pd.to_datetime(dfall.date)
print(dfall)

Output 的所有解决方案:

dfall[["date", "month"]]

        date  month
0 2020-01-31      1
1 2020-02-29      2
2 2020-03-31      3
3 2020-04-30      4
4 2020-05-31      5
5 2020-06-30      6

替代方法:

from datetime import datetime, timeldelta

def convert_date(date_str):
    date = datetime.strptime(date_str, '%Y-%m-%d')
    return (date - timedelta(days=date.day)).strftime('%Y-%m-%d')

dfall.date.apply(convert_date)

假设'date'列是字符串类型(否则使用.astype(str)strftime ),您可以将年月部分转换为datetime时间并减去一天的时间timedelta

dfall['lastdaylastmonth'] = pd.to_datetime(dfall['date'].str[:-3]) - pd.Timedelta(days=1)

# dfall['lastdaylastmonth']
# 0   2020-01-31
# 1   2020-02-29
# 2   2020-03-31
# 3   2020-04-30
# 4   2020-05-31
# 5   2020-06-30
# Name: lastdaylastmonth, dtype: datetime64[ns]
import datetime
from datetime import timedelta

df = pd.DataFrame({"date":['2020-02-04','2020-03-03','2020-04-02','2020-05-05','2020-06-03','2020-07-02'],
                  "month": [1,2,3,4,5,6]})

# Conert to data
def change_time_format(series):
    return datetime.datetime.strptime(series,"%Y-%m-%d")

df.date = df.date.apply(change_time_format)

dates = list(df.date)
previous_m_last_date = []
for d in dates:
    days = d.day
    u_date = d - timedelta(days)
    previous_m_last_date.append(u_date)

df["updated_date"] = previous_m_last_date
df

另一种方法:

import datetime

for index, d in df.iterrows():
    temp = d["date"]
    dtObj = datetime.datetime.strptime(temp, "%Y-%m-%d")
    newDt = dtObj - datetime.timedelta(days=dtObj.day)
    df["date"][index] = datetime.datetime.strftime(newDt, "%Y-%m-%d")

从日期时间导入日期时间

日期列表

日期 = [日期时间(2020, 2, 4), 日期时间(2020, 3, 3), 日期时间(2020, 4, 2), 日期时间(2020, 5, 5), 日期时间(2020, 6, 3), 日期时间( 2020, 7, 2)]

月份列的值

月 = [1, 2, 3, 4, 5, 6]

创建以日期为索引的系列

ts = pd.Series(月,索引=日期)

将日期移回一个月并存储在 date_col

date_col = ts.shift(-1, freq='M').index

使用修改日期作为 DataFrame 中的列

pd.DataFrame({'Dates': date_col, 'Month': month})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM