使用 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
"""
记录学习的点点滴滴