在转换为日期时间的列上使用 timedelta 和 strftime
Posted
技术标签:
【中文标题】在转换为日期时间的列上使用 timedelta 和 strftime【英文标题】:Using timedelta and strftime on column converted to datetime 【发布时间】:2021-08-16 03:13:13 【问题描述】:目标: 将 *.csv 读取到数据框后,我想将出生日期列转换为这种格式:%m-%d-%Y
。然后把它们写成excel。 *.csv 有 600K+ 记录。
总结:我有 20 世纪和 21 世纪的日期,而且这些年份有时会重叠。例如,我可以从 1901 年到 2001 年有四位数的年份。因此,我不得不使用从 this answer 借来的代码 sn-p。
我的尝试和预期:
我最初将该列转换为日期时间,并使用strftime('%m-%d-%Y')
。但是,那么 1970 年及之前的年份将被写为 20--。例如,这里的 2070 年和 2068 年应该分别是 1970 年和 1968 年。如果重要的话,生日列是dtype
object
。
import pandas as pd
from datetime import timedelta
from datetime import datetime
#birthdate column
birthdate = 'PATIENT_BIRTH_DATE'
#after reading the *.csv to a dataframe, convert the birthdate column to %m-%d-%Y format
df[birthdate] = pd.to_datetime(df[birthdate]).dt.strftime("%m-%d-%Y")
#prints
0 08-24-1996
1 10-16-1971
2 02-19-2070
3 09-25-2068
所以,我使用上面提到的代码 sn-p 来解决这个问题。但是,现在我似乎无法从写入 Excel 的日期中删除时间。如果我打印到终端,我没有时间,但是当我写到 Excel 时,我会。看起来像这样:1996-08-24 00:00:00
df[birthdate] = pd.to_datetime(df[birthdate])
future = df[birthdate] > datetime.today()
df.loc[future, birthdate] -= timedelta(days=365.25*100)
如果我在这里使用df[birthdate] = pd.to_datetime(df[birthdate]).dt.strftime("%m-%d-%Y")
,我会得到一个错误:TypeError: '>' not supported between instances of 'str' and 'datetime.datetime'
【问题讨论】:
澄清一下:基本上你的问题是你的数据源 (csv) 中有 2 位数的年份? @MrFuppes 这令人困惑。例如,*.csv 中的公式栏显示 6/7/1943。但字段值显示 7-Jun-43。所以,我不知道如何准确地回答你的问题。 但是您有 csv 格式的数据?还是 xls(x) 文件? - 如果是 csv,您可以在文本编辑器中打开它(例如,notepad++ 在 Windows 上很好)并检查“真实”格式,而不是 Excel 告诉您的格式。 Excel 喜欢为你考虑,这并不总是聪明的^^ 是的,源文件是*.csv格式。我用记事本++打开它,日期显示为 7-Jun-43。你到底在说什么? 这并不是说出来的那么简单。我只是好奇你用 2 位数的年份去哪里。 【参考方案1】:Excel 正在对其进行格式化,但您可以在写入工作簿时更新该选择。
您可以使用 xlsxwriter 引擎来指定给定列的格式。
https://xlsxwriter.readthedocs.io/example_pandas_column_formats.html
这里也是使用 xlsxwriter 格式化日期的指南,但我提供了一个解决方案,可以从下面推断出来
https://xlsxwriter.readthedocs.io/working_with_dates_and_time.html?highlight=date%20format
这仅在列是日期时间格式时才有效,因此可能需要验证使用此 sn-p
df['date1'] = df['date1'].dt.strftime('%m-%d-%Y')
然后运行以下命令,注意应用格式的列将根据数据框中的哪一列具有日期时间而改变。
df.to_excel(writer, sheet_name='Sheet1')
writer = pd.ExcelWriter("output.xlsx", engine='xlsxwriter')
# Get the xlsxwriter workbook and worksheet objects.
workbook = writer.book
worksheet = writer.sheets['Sheet1']
# %m-%d-%Y
format = workbook.add_format('num_format': 'mm-dd-yyyy')
# Set the column width and format.
worksheet.set_column('B:B', 18, format)
writer.save()
【讨论】:
我使用df[birthdate] = pd.to_datetime(df[birthdate], errors='coerce')
将该列转换为日期时间。然后我用了你的df['date1'] = df['date1'].dt.strftime('%m-%d-%Y')
。但是,我仍然无法通过TypeError: '>' not supported between instances of 'str' and 'Timestamp'
,它指的是这一行:df.loc[df[birthdate] > pd.Timestamp('now'), birthdate] -= pd.tseries.offsets.DateOffset(years=100)
。
所以听起来df.loc[df[birthdate] > pd.Timestamp('now'), birthdate] -= pd.tseries.offsets.DateOffset(years=100)
导致了错误。在您完成抵消过程后,我会转换 df['date1'] = df['date1'].dt.strftime('%m-%d-%Y')
。【参考方案2】:
我建议添加一个小补充,以说明 100 年的偏移量
import pandas as pd
birthdate = 'PATIENT_BIRTH_DATE'
df = pd.DataFrame(birthdate: pd.to_datetime(["08-24-1996", "10-16-1971", "02-19-2070", "09-25-2068"]))
df.loc[df[birthdate] > pd.Timestamp('now'), birthdate] -= pd.tseries.offsets.DateOffset(years=100)
df
PATIENT_BIRTH_DATE
0 1996-08-24
1 1971-10-16
2 1970-02-19
3 1968-09-25
而不是使用每年的平均天数。
“从不使用两位数年” 存储桶
+1。
【讨论】:
以上是关于在转换为日期时间的列上使用 timedelta 和 strftime的主要内容,如果未能解决你的问题,请参考以下文章