如何在熊猫中更改日期时间格式


109

我的数据框有一个DOB列(示例格式1/1/2016),默认情况下该列会转换为dtype'object'熊猫:DOB object

使用将日期转换为日期格式df['DOB'] = pd.to_datetime(df['DOB']),日期将转换为:2016-01-26,日期dtype为:DOB datetime64[ns]

现在,我想将此日期格式转换为01/26/2016任何其他通用日期格式或。我该怎么做?

无论我尝试哪种方法,它始终以2016-01-26格式显示日期。


您是否正在寻找仅在Jupyter Notebook下有效的解决方案?(在这种情况下,请使用每列的“样式”),或在普通的Python控制台和iPython中运行?
smci

Answers:


207

dt.strftime如果需要转换datetime为其他格式,可以使用(但请注意,dtype列的则为objectstring)):

import pandas as pd

df = pd.DataFrame({'DOB': {0: '26/1/2016', 1: '26/1/2016'}})
print (df)
         DOB
0  26/1/2016 
1  26/1/2016

df['DOB'] = pd.to_datetime(df.DOB)
print (df)
         DOB
0 2016-01-26
1 2016-01-26

df['DOB1'] = df['DOB'].dt.strftime('%m/%d/%Y')
print (df)
         DOB        DOB1
0 2016-01-26  01/26/2016
1 2016-01-26  01/26/2016

32
'strftime'将datetime列转换为unicode,以便在DOB1上应用该操作,我们再次必须将其转换为datetime。在不丢失data_type的情况下,还有其他格式化方法吗?
M.Zaman '17

@jezrael,有没有更好的解决方案,它还保留数据类型并且不将日期返回到对象列?问题是,如果尝试在解决方案建议的'df ['DOB1'] = df ['DOB']。dt.strftime('%m /%d /%Y')'行之后进行转换,在上方,日期将恢复为原始格式。
弃儿

哈哈,所以如果我想将此列用于.merge另一个数据框的datetime列,该怎么办?将另一个datetime列转换为object列来执行操作有意义.merge吗?
弃儿

是的,显然我同意,但是通过“不存在:(”,您说我不能在更改其格式后将其转换为日期时间而不丢失其新格式。所以吗?
播客

好的,据我所知,.merge即使这两列都是日期时间列,即使它们的格式不完全相同,也仍然可以正确完成。这是正确的吗?
弃儿

21

更改格式但不更改类型:

df['date'] = pd.to_datetime(df["date"].dt.strftime('%Y-%m'))

只要记住df [“ date”]在执行此操作之前应为datetime64
adhg

4
没有!假设该date列中某项的原始值为“ 2019年11月26日”。strftime()表示“时间串”,因此 df["date"].dt.strftime('%Y-%m')将是该项目的字符串 "2019-11"。然后,pd.to_datetime()将其转换这个字符串datetime64现在的格式,但作为“年11月1,2019”表!因此结果将是:没有格式更改,但是日期值本身发生了更改!
MarianD

2
@MarianD:您对单个答案的所有评论都是有用的,但是您能否在答案底部的“陷阱/不做这些”汇总中汇总一下?另外,您还需要清楚说明每一个问题是什么:如果任何输入日期的格式都不符合预期,则可能会引发异常或损坏日期。只需写“不!” 到处都无法传达这一点。
smci

8

下面的代码对我有用,而不是上一个-试试看!

df['DOB']=pd.to_datetime(df['DOB'].astype(str), format='%m/%d/%Y')

2
没有! 您的format='%m/%d/%Y'参数用于解析字符串,即应该以这种格式(例如"5/13/2019"提供字符串仅此而已,没有格式更改。2019-05-13如果df['DOB'].astype(str)包含的项目格式不正确(例如格式),它仍将显示为-或引发异常"2019-05-13"
MarianD

4

与第一个答案相比,我建议先使用dt.strftime(),然后再使用pd.to_datetime()。这样,它将仍然导致datetime数据类型。

例如,

import pandas as pd

df = pd.DataFrame({'DOB': {0: '26/1/2016 ', 1: '26/1/2016 '})
print(df.dtypes)

df['DOB1'] = df['DOB'].dt.strftime('%m/%d/%Y')
print(df.dtypes)

df['DOB1'] = pd.to_datetime(df['DOB1'])
print(df.dtypes)

2
至少在我看来,这是行不通的。具体来说,该列将转换为日期时间数据类型,但值也将转换为原始格式!
弃儿

没有!语法错误(缺少大括号),在我的Pandas(0.25.1)版本中,另一个语法错误(dt.strftime()-只能使用具有datetimelike值的.dt访问器)-您依赖于固有的数据类型,但是在不同版本的大熊猫的固有数据类型可能有所不同),还有一个奇怪的逻辑- 为什么将datetime转换为字符串,然后再转换回datetime?请参阅我对rishi jain的回答的评论。
MarianD

2

两者之间有区别

  • 数据帧单元的内容(二进制值)和
  • 它对我们(人类)的演示(展示)。

所以问题是:如何在不更改数据/数据类型本身的情况下达到我的数据的适当表示

答案是:

  • 如果您使用Jupyter笔记本显示数据,或者
  • 如果您想以HTML文件的形式进行演示(即使准备了许多多余的属性idclass属性来进行进一步的 CSS样式设置,则可以使用也可以不使用它们),

使用样式样式不会更改数据框列的数据/数据类型。

现在,我向您展示如何在Jupyter笔记本中找到它-有关HTML文件形式的演示文稿,请参阅问题末尾的注释。

我将假设您的列DOB 已经具有该类型datetime64(您已表明知道如何访问它)。我准备了一个简单的数据框(只有一列),向您展示了一些基本样式:

  • 没有样式:

       df
          DOB
0  2019-07-03
1  2019-08-03
2  2019-09-03
3  2019-10-03
  • 样式为mm/dd/yyyy

       df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})
          DOB
0  07/03/2019
1  08/03/2019
2  09/03/2019
3  10/03/2019
  • 样式为dd-mm-yyyy

       df.style.format({"DOB": lambda t: t.strftime("%d-%m-%Y")}) 
          DOB
0  03-07-2019
1  03-08-2019
2  03-09-2019
3  03-10-2019

小心!
返回的对象不是数据框-它是类的对象Styler,因此请勿将其分配回df

不要这样做:

df = df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})    # Don´t do this!

(每个数据框都可以通过其.style属性访问其Styler对象,我们更改了该df.style对象,而不是数据框本身。)


问题和解答:

  • 问: 为什么在Jupyter笔记本单元格中用作最后一条命令的Styler对象(或返回它的表达式)显示您的(样式化)表,而不显示Styler对象本身?

  • 答:因为每个Styler对象都有一个回调方法._repr_html_(),该方法返回用于呈现数据框的HTML代码(作为漂亮的HTML表)。

    Jupyter Notebook IDE 自动调用此方法以呈现具有此方法的对象。


注意:

您不需要Jupyter笔记本进行样式设置(即,在不更改数据/数据类型的情况下很好地输出数据框)。

render()如果您想使用HTML代码获取字符串(例如,用于将格式化的数据帧发布到Web上,或仅以HTML格式显示表格),则Styler对象也具有一种方法:

df_styler = df.style.format({"DOB": lambda t: t.strftime("%m/%d/%Y")})
HTML_string = df_styler.render()

值得指出的是,这样的样式器代码旨在在其下运行,并且仅在Jupyter Notebook下生效,并且在控制台或iPython中运行时的效果绝对为零。OP没有指定“在Jupyter下”,因此,根据其设置,这可能是也可能不是可行的解决方案。许多数据科学代码被复制粘贴,而Jupyter特定的假设没有得到明确指定,然后人们想知道为什么在其(控制台)环境中运行样式器代码“不起作用”。
smci

@smci,我的答案的第二段中没有明确提及吗?以条件if语句的形式,每个程序员都知道吗?—尽管它感谢您的评论,但对某些人可能会有帮助。
MarianD

不,这不是很清楚,也被掩埋了。最初的问题与Jupyter无关,并且OP和某些用户甚至没有可用的Jupyter。您的答案需要大胆地说出它的第一行“以下方法(样式)仅在Jupyter笔记本电脑下有效,而在Jupyter笔记本电脑上运行时则无效”。(在数据科学博客和站点中,我每天看到人们将Jupyter代码发布到非Jupyter环境中,并想知道为什么它不起作用)。
smci

凉。我还建议您添加在其他“使用strftime转换为字符串然后再次使用pd.to_datetime转换为字符串”方法中确定的所有(许多)陷阱。至少需要提及引发和捕获异常。此外,pd.to_datetime()还具有参数errors='raise'/'coerce'/'ignore', dayfirst, yearfirst, utc, exact来控制其精确度和异常满足程度,以及无效输出是否被强制执行NaT或强制执行什么操作。使“现实世界”数据集中更加复杂的是混合/缺失/不完整的格式,时间,时区等。例外不一定是坏事。
smci

...否则我可以将其写为非Jupyter方法中的陷阱汇总。
smci

1

下面的代码更改为“ datetime”类型,并以给定的格式字符串格式化。效果很好!

df['DOB']=pd.to_datetime(df['DOB'].dt.strftime('%m/%d/%Y'))

2
更改为:df['DOB']=pd.to_datetime(df['DOB']).dt.strftime('%m/%d/%Y')
John Doe

没有!- 为什么要将datetime转换为字符串,然后再转换回datetime?请参阅我对其他答案的评论。
MarianD

1

您可以尝试将日期格式转换为DD-MM-YYYY:

df['DOB'] = pd.to_datetime(df['DOB'], dayfirst = True)

没有! dayfirst=True只是日期解析顺序的说明,例如,将歧义的日期字符串“ 2-1-2019”解析为2019年1月2日,而不是2019年2月1日。除此之外,输出格式也没有任何更改
MarianD
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.