pandas.to_datetime()自动转换为<M8 [ns],并且无法使用numpy.isnat()

时间:2019-10-21 16:53:43

标签: python pandas numpy dataframe

我有一个数据帧,该数据帧被读取为包含日期的字符串,格式为“ YYYY-MM-DD”。我已经使用pd.to_datetime(带有强制)将列转换为datetime,并且打算使用numpy.isnat()在该列中搜索NaT。

defaultDate = datetime.datetime(2020, 12, 31)
df['dates'] = pd.to_datetime(df['dates'], errors = 'coerce')
df['newDates'] = [x if ~np.isnat(x) else defaultDate for x in df['dates']]

当我尝试运行代码时,出现错误:

**TypeError**: ufunc 'isnat' is only defined for datetime and timedelta.
后来我发现该列的dtype已转换为

2 个答案:

答案 0 :(得分:0)

<M8[ns]datetime64[ns]的同义词。另外,如果您要处理的是熊猫np.isnat,则不需要datetime

defaultDate = pd.to_datetime('2020-12-31')
df['newDates'] = [x if ~np.isnat(x) else defaultDate for x in df['dates']]
df['newDates'] = df['dates'].fillna(defaultDate)

答案 1 :(得分:0)

看起来像isnat的目的是测试像这样的数组:

In [47]: np.array([0,1,'NaT'], 'datetime64[D]')                                 
Out[47]: array(['1970-01-01', '1970-01-02',        'NaT'], dtype='datetime64[D]')
In [48]: np.isnat(_)                                                            
Out[48]: array([False, False,  True])

我不得不尝试找出如何生成NaT元素。可能还有其他方法。

您能否提供一个包含样本值(有效日期和非日期)的数据框或系列。这将使探索过滤方法变得更加容易。我相信熊猫具有某种非一次性的元素,但我不知道它是否与numpy兼容。同样要记住,当Series元素包含字符串和pandas时,None会很容易切换到对象dtype。

测试系列:

In [50]: ds = pd.Series(_47)                                                    
In [51]: ds                                                                     
Out[51]: 
0   1970-01-01
1   1970-01-02
2          NaT
dtype: datetime64[ns]
In [52]: ds.isna()                                                              
Out[52]: 
0    False
1    False
2     True
dtype: bool
In [54]: ds.isnull()                                                            
Out[54]: 
0    False
1    False
2     True
dtype: bool

更改系列的元素:

In [58]: ds[2]=12                                                               
In [59]: ds                                                                     
Out[59]: 
0    1970-01-01 00:00:00
1    1970-01-02 00:00:00
2                     12
dtype: object

更改dtype

In [60]: ds.values                                                              
Out[60]: 
array([Timestamp('1970-01-01 00:00:00'), Timestamp('1970-01-02 00:00:00'),
       12], dtype=object)
In [61]: np.isnat(_)                                                            
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-61-47ce91c66a51> in <module>
----> 1 np.isnat(_)

TypeError: ufunc 'isnat' is only defined for datetime and timedelta.

可能的转换顺序:

包含日期和其他内容的系列,对象dtype:

In [118]: ds                                                                    
Out[118]: 
0    1970-01-01 00:00:00
1    1970-01-02 00:00:00
2                     12
dtype: object
In [119]: ds1=pd.to_datetime(ds,errors='coerce')                                
In [120]: ds1                                                                   
Out[120]: 
0   1970-01-01
1   1970-01-02
2          NaT
dtype: datetime64[ns]

强制转换会产生NaT

In [121]: idx = np.isnat(ds1)                                                   
In [122]: idx                                                                   
Out[122]: 
0    False
1    False
2     True
dtype: bool
In [123]: ds1[idx]                                                              
Out[123]: 
2   NaT
dtype: datetime64[ns]

定义正确的默认值;它的dtype很重要,因为熊猫很容易更改dtype(numpy不会):

In [124]: default= np.array('2020-12-31','datetime64[ns]')[()]                  
In [125]: default                                                               
Out[125]: numpy.datetime64('2020-12-31T00:00:00.000000000')
In [126]: ds1[idx]=default                                                      
In [127]: ds1                                                                   
Out[127]: 
0   1970-01-01
1   1970-01-02
2   2020-12-31
dtype: datetime64[ns]