为什么在pandas中将列从datetime转换为字符串不能使用.loc?

fjnneemd  于 2023-05-05  发布在  其他
关注(0)|答案(1)|浏览(134)

我使用pandas从Excel加载数据,生成的DataFrame包含字符串和日期。包含字符串的列的数据类型为“object”,而日期列的数据类型为“datetime 64 [ns]”。在我的代码中的某个时候,我需要将一列从datetime转换为字符串以写回Excel,但是如果我尝试使用对我来说最明显的方式,并且根据文档似乎是推荐的方式,pandas不会让我这样做:使用.loc获取要更改的列,并将它们与转换为字符串的相同列分配。
我已经找到了绕过这个问题的方法,让Pandas做我需要的事情,但要么这是一个错误,要么我不明白一些潜在的机制,从长远来看,这些机制可能会回来咬我,因此我的问题。
重现此情况的代码(在pandas 2.0.0和2.0.1中都出现过,这 * 可能 * 会导致问题)如下(在我使用的实际DataFrame中,有很多列):

import pandas as pd

not_yet_datetime_df = pd.DataFrame([["2023-01-06", "2023-01-06", "2023-01-06", "2023-01-06", "2023-01-06"]]).T
datetime_df = not_yet_datetime_df.astype("datetime64[ns]")
datetime_df.loc[:, 0] = datetime_df.loc[:, 0].dt.strftime("%d.%m.%Y")
datetime_df.loc[:, 0] = datetime_df.loc[:, 0].astype("object")  # neither of these two will work for me
print(datetime_df.dtypes)  # will return "datetime64[ns]" for this single column

有多种方法可以绕过这个问题,包括简单地用datetime_df[0] = datetime_df.loc[:, 0].dt.strftime("%d.%m.%Y")替换第5行(省略等号左边的.loc),我至少可以用datetime_df = datetime_df.astype({0:"object"})将列变为“object”dtype,但我不太明白为什么特别是第一个解决方案有效,以及我对.loc或一般日期时间的误解。
我读了一点pandas 2.0.0在返回视图和副本,但据我(有限)的理解,这不应该受到任何2.0.0的变化。
有谁能帮我弄明白这到底是怎么回事吗?我喜欢使用.loc而不是只使用[]-括号赋值,我觉得它不像我希望的那样直观。

7vux5j2d

7vux5j2d1#

另请参见Does .loc[:, ['A','B']] assignment allow to change the dtype of the columns?-.loc尝试强制转换回原始类型。文档中有一个注解,可能很难找到:
当尝试使用astype()和loc()将列的子集转换为指定的类型时,将发生向上转换。
不管怎样,这就是为什么它一直是datetime 64 [ns]。为了演示,如果将datetime格式更改为pandas的解析器不接受的格式,则“向上转换”失败,并保留dtype:

import pandas as pd

not_yet_datetime_df = pd.DataFrame([["2023-01-06", "2023-01-06", "2023-01-06", "2023-01-06", "2023-01-06"]]).T
datetime_df = not_yet_datetime_df.astype("datetime64[ns]")
datetime_df.loc[:, 0] = datetime_df.loc[:, 0].dt.strftime("%d. asdf %m. xx %Y")
print(datetime_df.dtypes) 
# 0    object
# dtype: object

总的来说,我仍然认为在这种情况下,最基本的[ ]可以安全地将您带到您想要的地方。如果你创建一个新的列,你既不是切片,也不是选择,也不是索引。如果您替换一个列(例如string with datetime dtype Series;你在这里选择了一些东西……)。所以我不认为在这里首先使用loc有什么意义。

相关问题