使用 iloc 或 loc 多列数据类型进行转换,源数据类型修失败

# 使用 iloc 或 loc 多列数据类型进行转换,源数据类型修失败

import pandas as pd
import numpy as np
#在利用iloc对数据框中列的类型进行修改时,可以看到数据类型并没有改变
df = pd.DataFrame([['2020-01-01', '2020-06-30', 'A'],
                   ['2020-07-01', '2020-12-31', 'B']],
                  columns=['start_date', 'end_date', 'field1'])
print(df.dtypes)
df.iloc[:,0:2] = df.iloc[:,0:2].apply(pd.to_datetime)
print("*************************************")
print(df.dtypes)
"""
输出结果
start_date    object
end_date      object
field1        object
dtype: object
*************************************
start_date    object
end_date      object
field1        object
dtype: object
"""

#但是可以通过下面方法就行修改
df[['start_date', 'end_date']] = df[['start_date', 'end_date']].apply(pd.to_datetime)
"""
start_date    datetime64[ns]
end_date      datetime64[ns]
field1                object
"""


#这个问题困扰了好久了,直到今天在stackoverflow上看到一个老哥的回答,算是把这个问题解决了
# - pandas1.3.0版本之前改方法是可以的,在1.3.0之后就不可以了
# - 原因在于使用 loc 和 iloc 设置值时尝试原地操作:当使用 loc 或 iloc 设置整个列时,pandas 将尝试将值插入现有数据而不是创建一个全新的数组,这意味着如果新数组适合现有类型,iloc 和 loc 将尝试不更改数组的数据类型。
# - 相反:设置 frame[keys] = values 时将禁止原地操作,新的数组将替代原有的数据,结果,列将保留值的数据类型,永远不会转换为现有数组的数据类型。

#考虑到这些变化,我们现在可以这样做

import pandas as pd

df = pd.DataFrame([['2020-01-01', '2020-06-30', 'A'],
                   ['2020-07-01', '2020-12-31', 'B']],
                  columns=['start_date', 'end_date', 'field1'])

cols = df.columns[0:2]
df[cols] = df[cols].apply(pd.to_datetime)
# or
# df[df.columns[0:2]] = df.iloc[:, 0:2].apply(pd.to_datetime)

print(df)
print(df.dtypes)
"""
输出结果
 start_date   end_date field1
0 2020-01-01 2020-06-30      A
1 2020-07-01 2020-12-31      B
start_date    datetime64[ns]
end_date      datetime64[ns]
field1                object
dtype: object
"""



posted @ 2023-03-02 10:40  小杨的冥想课  阅读(98)  评论(0编辑  收藏  举报