设置astype时Datetime失败,日期已损坏



我正在导入一个包含20个变量和1500条记录的csv。有5个日期列采用英国日期格式dd/mm/yyyy,并以.str导入我需要能够区分一个日期和另一个日期。这是医院的住院时间,我需要从住院日期中减去出院日期来计算住院时间。我遇到了很多问题。为了说明,我使用了两列。

import pandas as pd
import numpy as np
from datetime import datetime

import.csv

df = pd.read_csv("/Users........csv", usecols = ['ADMIDATE', 'DISDATE'])
df
ADMIDATE    DISDATE
0   04/02/2018  07/02/2018
1   25/07/2017  1801-01-01
2   28/06/2017  01/07/2017
3   22/06/2017  1801-01-01
4   11/12/2017  15/12/2017
... ... ...
1503    25/01/2019  27/01/2019
1504    31/08/2018  1801-01-01
1505    20/09/2018  05/11/2018
1506    28/09/2018  1801-01-01
1507    21/02/2019  24/02/2019
1508 rows × 2 columns

我删除了大约100条DISDATE为1801-01-01的记录,这些可能是收集数据时仍在医院的患者的不良数据。为了将日期转换为日期时间,我使用了.astype('datetime64[ns](这是因为我不知道如何在多列上使用pd.to_datetime。

df[['ADMIDATE', 'DISDATE']] = df[['ADMIDATE', 'DISDATE']].astype('datetime64[ns]')
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1399 entries, 0 to 1398
Data columns (total 3 columns):
#   Column      Non-Null Count  Dtype         
---  ------      --------------  -----         
0   Unnamed: 0  1399 non-null   int64         
1   ADMIDATE    1399 non-null   datetime64[ns]
2   DISDATE     1391 non-null   datetime64[ns]
dtypes: datetime64[ns](2), int64(1)
memory usage: 32.9 KB

因此,这种转变似乎奏效了。但是,在检查数据时,ADMIDATE变为yyyy-mm-dd,DISDATE变为yyyy-dd-mm。

df.head(20)
Unnamed: 0  ADMIDATE    DISDATE
0   0   2018-04-02  2018-07-02
1   2   2017-06-28  2017-01-07
2   4   2017-11-12  2017-12-15
3   5   2017-09-04  2017-12-04
4   6   2017-05-30  2017-01-06
5   7   2017-02-08  2017-07-08
6   8   2017-11-17  2017-11-18
7   9   2018-03-14  2018-03-20
8   10  2017-04-26  2017-03-05
9   11  2017-05-16  2017-05-17
10  12  2018-01-17  2018-01-19
11  13  2017-12-18  2017-12-20
12  14  2017-02-10  2017-04-10
13  16  2017-03-30  2017-07-04
14  17  2017-01-12  2017-12-18
15  18  2017-12-07  2017-07-14
16  19  2017-05-04  2017-08-04
17  20  2017-10-30  2017-01-11
18  21  2017-06-19  2017-06-22
19  22  2017-04-05  2017-08-05

因此,当我从DISDATE中减去ADMIDATE时,我会得到负值。

df['DISDATE'] - df['ADMIDATE']
0        91 days
1      -172 days
2        33 days
3        91 days
4      -144 days
...   
1394    188 days
1395   -291 days
1396      2 days
1397   -132 days
1398      3 days
Length: 1399, dtype: timedelta64[ns]

我想要一个适用于我所有日期列的方法,保持英国格式,并允许我对日期字段进行基本操作。

在@codedifferent的建议之后,这在下似乎非常明智

for col in df.columns:
df[col] = pd.to_datetime(df[col], dayfirst=True, errors='coerce')

尽管dayfirst=True,但格式保持不变。

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1399 entries, 0 to 1398
Data columns (total 3 columns):
#   Column      Non-Null Count  Dtype         
---  ------      --------------  -----         
0   Unnamed: 0  1399 non-null   datetime64[ns]
1   ADMIDATE    1399 non-null   datetime64[ns]
2   DISDATE     1391 non-null   datetime64[ns]
dtypes: datetime64[ns](3)
memory usage: 32.9 KB
df.head()
Unnamed: 0  ADMIDATE    DISDATE
0   1970-01-01 00:00:00.000000000   2018-04-02  2018-07-02
1   1970-01-01 00:00:00.000000002   2017-06-28  2017-01-07
2   1970-01-01 00:00:00.000000004   2017-11-12  2017-12-15
3   1970-01-01 00:00:00.000000005   2017-09-04  2017-12-04
4   1970-01-01 00:00:00.000000006   2017-05-30  2017-01-06

我也试过format='%d%m%Y',今年仍然是第一年。datetime.strptime有什么好处吗?。

只需告诉pandas.to_datetime使用特定且适当的格式,例如:

import pandas as pd
import numpy as np
df = pd.DataFrame({'ADMIDATE': ['04/02/2018', '25/07/2017', 
'28/06/2017', '22/06/2017', '11/12/2017'],
'DISDATE': ['07/02/2018', '1801-01-01', 
'01/07/2017', '1801-01-01', '15/12/2017']}).replace({'1801-01-01': np.datetime64('NaT')})

for col in ['ADMIDATE', 'DISDATE']:
df[col] = pd.to_datetime(df[col], format='%d/%m/%Y')
# df
#     ADMIDATE    DISDATE
# 0 2018-02-04 2018-02-07
# 1 2017-07-25        NaT
# 2 2017-06-28 2017-07-01
# 3 2017-06-22        NaT
# 4 2017-12-11 2017-12-15    
#   Column    Non-Null Count  Dtype         
# ---  ------    --------------  -----         
#  0   ADMIDATE  5 non-null      datetime64[ns]
#  1   DISDATE   3 non-null      datetime64[ns]
# dtypes: datetime64[ns](2)

注意:将'1801-01-01'替换为np.datetime64('NaT'),这样在调用pd.to_datetime时就不必忽略错误。

to_datetime是您想要的函数。它不支持多列,所以您只需在列上逐个循环。字符串是英国格式(第一天(,所以你只需告诉to_datetime

df = pd.read_csv('/path/to/file.csv', usecols = ['ADMIDATE','DISDATE']).replace({'1801-01-01': pd.NA})
for col in df.columns:
df[col] = pd.to_datetime(df[col], dayfirst=True, errors='coerce')

astype('datetime64[ns]')对于您所需要的内容过于灵活。

相关内容

最新更新