Numpy Where将时间戳/日期时间更改为整数

11

不是问题,只是有些困惑。

我有一列日期,看起来像这样:

0              NaT
1       1996-04-01
2       2000-03-01
3              NaT
4              NaT
5              NaT
6              NaT
7              NaT
8              NaT

我希望您能将NaTs转换为静态值。 (假设我已经导入了pandas作为pd和numpy作为np)。
如果我执行以下操作:
mydata['mynewdate'] = mydata.mydate.replace(
    np.NaN, pd.datetime(1994,6,30,0,0))

一切都好,我明白了:

0       1994-06-30
1       1996-04-01
2       2000-03-01
3       1994-06-30
4       1994-06-30
5       1994-06-30
6       1994-06-30
7       1994-06-30
8       1994-06-30

但是如果我这样做:
mydata['mynewdate'] = np.where(
    mydata['mydate'].isnull(), pd.datetime(1994,6,30,0,0),mydata['mydate'])

我得到:
0        1994-06-30 00:00:00
1         828316800000000000
2         951868800000000000
3        1994-06-30 00:00:00
4        1994-06-30 00:00:00
5        1994-06-30 00:00:00
6        1994-06-30 00:00:00
7        1994-06-30 00:00:00
8        1994-06-30 00:00:00

此操作将原始的非空日期转换为整数。我认为可能存在数据类型混淆,因此进行了这个操作:

mydata['mynewdate'] = np.where(
    mydata['mydate'].isnull(), pd.datetime(1994,6,30,0,0),pd.to_datetime(mydata['mydate']))

仍然是这样得到:

0        1994-06-30 00:00:00
1         828316800000000000
2         951868800000000000
3        1994-06-30 00:00:00
4        1994-06-30 00:00:00
5        1994-06-30 00:00:00
6        1994-06-30 00:00:00
7        1994-06-30 00:00:00
8        1994-06-30 00:00:00

请注意(不要问):是的,我有更好的解决方案来替换null。这个问题不是关于替换null(正如标题所示),而是关于numpy where如何处理日期。我提出这个问题是因为未来我将有更复杂的条件来选择要替换的日期,并且认为numpy where可以胜任。
有什么想法吗?
4个回答

9
由于Numpy的datetime64、Pandas的Timestamp和/或datetime.datetime之间不稳定的交互作用,出现了这个问题。我通过从一开始就将替换值设置为numpy.datetime64来解决了这个问题。
static_date = np.datetime64('1994-06-30')
# static_date = np.datetime64(pd.datetime(1994, 6, 30))

mydata.assign(
    mynewdate=np.where(
        mydata.mydate.isnull(),
        static_date,
        mydata.mydate
    )
)

      mydate  mynewdate
0        NaT 1994-06-30
1 1996-04-01 1996-04-01
2 2000-03-01 2000-03-01
3        NaT 1994-06-30
4        NaT 1994-06-30
5        NaT 1994-06-30
6        NaT 1994-06-30
7        NaT 1994-06-30
8        NaT 1994-06-30

很好。我想这就是这样的事情。我还没有找到正确的转换方法来使它工作。直接使用:mydata['mynewdate'] = np.where(mydata['mydate'].isnull(), np.datetime64('1994-06-30'),mydata['mydate']) 也可以工作。 - user7969724
@Vaishali:请注意我帖子末尾的评论:“请注意(不要问):是的,我有一个更好的解决方案来替换null。这个问题不是关于替换null(正如标题所示),而是关于numpy如何处理日期。我之所以问是因为将来我会有更复杂的条件来选择要替换的日期,并且认为numpy where可以胜任。” - user7969724

2

如果你正在使用 pandas,建议尝试使用 mask/where 函数。

df.mask(df['Date'].isnull(), pd.to_datetime('1994-06-30'))
Out[824]: 
        Date
0 1994-06-30
1 1996-04-01
2 2000-03-01
3 1994-06-30
4 1994-06-30
5 1994-06-30
6 1994-06-30
7 1994-06-30
8 1994-06-30

1
谢谢。但是就像我说的,我问这个问题是因为将来我会有一些相当复杂的条件需要测试,而掩码可能不太够用。 - user7969724

0

一种选择是使用列表推导式,类似下面的代码应该可以工作:

mydata['mynewdate'] = [pd.datetime(1994,6,30,0,0) if pd.isna(mydata.loc[j,'mydate']) else mydata.loc[j,'mydate'] for j in mydata.index]

0
刚刚遇到了一个非常类似的问题(我使用了numpy的.where()函数,但问题的表现是一样的)。我不知道为什么这样做有效,但确实有效(下面解释了一个注意事项)。
原始代码:
df['date']  = np.where(df['date'].between(df['start'], df['end']), df['date'], None)

但是这导致了一个带有纳秒日期的“日期”列(例如1656374400000000000)
更新的代码:
df['date']  = np.where(df['date'].between(df['start'], df['end']), df['date'].astype(str), None)

唯一的区别在于末尾的astype(str)部分。这将返回一个与我最初使用的'YYYY-mm-dd'格式相同的日期。
这里的注意事项是之前的datetime.datetime数据类型被转换为字符串,但是很容易转换回来,我甚至可以通过将整个过程包装在pd.to_datetime()函数中来实现,但为了清晰起见,在这里省略了它。

我不确定这是否对原始的五年前的问题有太大的帮助。pandas自那时以来已经发生了变化(例如pd.datetime不再起作用)。至少你需要清楚df['date']包含什么,dtype是什么,如果是对象,又是什么类型。在Python、NumPy和pandas中有很多表达日期的方式。一个有用的答案应该帮助我们一致地匹配这些方式,而不仅仅是给我们另一种(令人困惑的)混合方式。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接