使用.loc和slice设置时,Datetime列被强制转换为int

时间:2019-06-05 01:51:03

标签: pandas datetime slice

我有一列日期时间,需要将其中一些值更改为新的日期时间。当我使用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

有人可以解释一下造成强迫的原因以及如何防止这种情况吗?我使用此代码编写的代码是一个月前编写的,并且可以正常工作,这是否可能是有关未来熊猫版本过时某些功能的警告之一?

对所发生的事情的解释将不胜感激,因为我编写了可能采用类似功能的其他代码,以确保一切按预期进行。

2 个答案:

答案 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。

相关问题