我有一列日期时间,需要将其中一些值更改为新的日期时间。当我使用df.loc [indices,'col'] = new_datetimes设置值时,当新设置的值位于datetime时,未受影响的值被强制为int。如果我一次设置一个值,则不会发生类型强制。
为说明起见,我创建了一个只有一列的示例df。
df = pd.DataFrame([dt.datetime(2019,1,1)]*5)
df.loc[[1,3,4]] = [dt.datetime(2019,1,2)]*3
df
这将产生以下结果: output
如果我分别更改索引1,3,4:
df = pd.DataFrame([dt.datetime(2019,1,1)]*5)
df.loc[1] = dt.datetime(2019,1,2)
df.loc[3] = dt.datetime(2019,1,2)
df.loc[4] = dt.datetime(2019,1,2)
df
我得到正确的输出: output
建议在设置之前将列表转换为numpy数组,这确实可以解决问题。但是,如果尝试使用numpy数组设置多个列(其中一些不是日期时间),则会再次出现此问题。
在此示例中,数据框有两列,我尝试设置这两列。
df = pd.DataFrame({'dt':[dt.datetime(2019,1,1)]*5, 'value':[1,1,1,1,1]})
df.loc[[1,3,4]] = np.array([[dt.datetime(2019,1,2)]*3, [2,2,2]]).T
df
给出以下输出: output
有人可以解释一下造成强迫的原因以及如何防止这种情况吗?我使用此代码编写的代码是一个月前编写的,并且可以正常工作,这是否可能是有关未来熊猫版本过时某些功能的警告之一?
对所发生的事情的解释将不胜感激,因为我编写了可能采用类似功能的其他代码,以确保一切按预期进行。
答案 0 :(得分:2)
w-m 提出的解决方案具有“笨拙的细节” 结果列中还包含时间部分(没有) 之前)。
我也有这样的说法:DataFrames是表而不是 Series , 所以他们有列,每个列都有其名称,这是一个坏习惯 依靠默认的列名(连续的数字)。
因此,我提出了另一种解决上述两个问题的解决方案:
要创建我执行的源DataFrame:
df = pd.DataFrame([dt.datetime(2019, 1, 1)]*5, columns=['c1'])
请注意,我为唯一的列提供了名称。
然后我创建了另一个 DataFrame:
df2 = pd.DataFrame([dt.datetime(2019,1,2)]*3, columns=['c1'], index=[1,3,4])
它包含您的“新”日期和您在 loc 中使用的数字 我设置为索引(再次使用相同的列名)。
然后,要更新 df ,请使用(毫不奇怪) df.update :
df.update(df2)
此函数执行就地更新,因此,如果您 print(df),您将获得:
c1
0 2019-01-01
1 2019-01-02
2 2019-01-01
3 2019-01-02
4 2019-01-02
如您所见,在索引1、3和4下您有新的日期 就像以前一样,没有时间部分。
答案 1 :(得分:1)
[dt.datetime(2019,1,2)]*3
是对象的Python列表。这个特定的列表恰好只包含日期时间,但是Pandas似乎不认识它,而是按原样对待-任何类型的对象的列表。
如果将其转换为类型化数组,则Pandas将保留该列的原始dtype:
df.loc[[1,3,4]] = np.asarray([dt.datetime(2019,1,2)]*3)
我希望此解决方法对您有所帮助,但您可能仍想向Pandas提交错误。在第一个输出示例中,我没有解释为什么将datetime对象强制转换为int。